@carmaclouds/core 2.3.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/cache/CacheManager.d.ts.map +1 -0
- package/dist/cache/CacheManager.js +131 -0
- package/dist/cache/CacheManager.js.map +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +22 -0
- package/dist/index.js.map +1 -0
- package/dist/ir/index.d.ts +11 -0
- package/dist/ir/index.d.ts.map +1 -0
- package/dist/ir/index.js +9 -0
- package/dist/ir/index.js.map +1 -0
- package/dist/ir/normalize.d.ts +10 -0
- package/dist/ir/normalize.d.ts.map +1 -0
- package/dist/ir/normalize.js +207 -0
- package/dist/ir/normalize.js.map +1 -0
- package/dist/ir/persistence.d.ts +26 -0
- package/dist/ir/persistence.d.ts.map +1 -0
- package/dist/ir/persistence.js +21 -0
- package/dist/ir/persistence.js.map +1 -0
- package/dist/ir/sync.d.ts +12 -0
- package/dist/ir/sync.d.ts.map +1 -0
- package/dist/ir/sync.js +36 -0
- package/dist/ir/sync.js.map +1 -0
- package/dist/ir/types.d.ts +143 -0
- package/dist/ir/types.d.ts.map +1 -0
- package/dist/ir/types.js +13 -0
- package/dist/ir/types.js.map +1 -0
- package/dist/ir/views/dnd5e.d.ts +40 -0
- package/dist/ir/views/dnd5e.d.ts.map +1 -0
- package/dist/ir/views/dnd5e.js +50 -0
- package/dist/ir/views/dnd5e.js.map +1 -0
- package/dist/render/character.d.ts +19 -0
- package/dist/render/character.d.ts.map +1 -0
- package/dist/render/character.js +156 -0
- package/dist/render/character.js.map +1 -0
- package/dist/render/h.d.ts +27 -0
- package/dist/render/h.d.ts.map +1 -0
- package/dist/render/h.js +64 -0
- package/dist/render/h.js.map +1 -0
- package/dist/render/index.d.ts +11 -0
- package/dist/render/index.d.ts.map +1 -0
- package/dist/render/index.js +8 -0
- package/dist/render/index.js.map +1 -0
- package/dist/render/mount.d.ts +31 -0
- package/dist/render/mount.d.ts.map +1 -0
- package/dist/render/mount.js +63 -0
- package/dist/render/mount.js.map +1 -0
- package/dist/supabase/fields.d.ts.map +1 -0
- package/dist/supabase/fields.js +120 -0
- package/dist/supabase/fields.js.map +1 -0
- package/dist/types/character.d.ts.map +1 -0
- package/dist/types/character.js +5 -0
- package/dist/types/character.js.map +1 -0
- package/package.json +73 -0
- package/src/browser.js +51 -0
- package/src/cache/CacheManager.ts +174 -0
- package/src/common/browser-polyfill.js +319 -0
- package/src/common/debug.js +123 -0
- package/src/common/html-utils.js +134 -0
- package/src/common/theme-manager.js +265 -0
- package/src/index.ts +25 -0
- package/src/ir/__fixtures__/dnd5e-character.json +75962 -0
- package/src/ir/__fixtures__/non-dnd-character.json +14218 -0
- package/src/ir/index.ts +10 -0
- package/src/ir/normalize.ts +245 -0
- package/src/ir/persistence.ts +37 -0
- package/src/ir/sync.ts +49 -0
- package/src/ir/types.ts +161 -0
- package/src/ir/views/dnd5e.ts +94 -0
- package/src/lib/indexeddb-cache.js +320 -0
- package/src/modules/action-announcements.js +102 -0
- package/src/modules/action-display.js +1557 -0
- package/src/modules/action-executor.js +860 -0
- package/src/modules/action-filters.js +167 -0
- package/src/modules/action-options.js +117 -0
- package/src/modules/card-creator.js +142 -0
- package/src/modules/character-portrait.js +169 -0
- package/src/modules/character-trait-popups.js +959 -0
- package/src/modules/character-traits.js +814 -0
- package/src/modules/class-feature-edge-cases.js +1320 -0
- package/src/modules/color-utils.js +69 -0
- package/src/modules/combat-maneuver-edge-cases.js +660 -0
- package/src/modules/companions-manager.js +178 -0
- package/src/modules/concentration-tracker.js +178 -0
- package/src/modules/data-manager.js +514 -0
- package/src/modules/dice-roller.js +719 -0
- package/src/modules/effects-manager.js +743 -0
- package/src/modules/feature-modals.js +1264 -0
- package/src/modules/formula-resolver.js +444 -0
- package/src/modules/gm-mode.js +184 -0
- package/src/modules/health-modals.js +399 -0
- package/src/modules/hp-management.js +752 -0
- package/src/modules/inventory-manager.js +242 -0
- package/src/modules/macro-system.js +825 -0
- package/src/modules/notification-system.js +92 -0
- package/src/modules/racial-feature-edge-cases.js +746 -0
- package/src/modules/resource-manager.js +775 -0
- package/src/modules/sheet-builder.js +654 -0
- package/src/modules/spell-action-modals.js +583 -0
- package/src/modules/spell-cards.js +602 -0
- package/src/modules/spell-casting.js +723 -0
- package/src/modules/spell-display.js +314 -0
- package/src/modules/spell-edge-cases.js +509 -0
- package/src/modules/spell-macros.js +201 -0
- package/src/modules/spell-modals.js +1221 -0
- package/src/modules/spell-slots.js +224 -0
- package/src/modules/status-bar-bridge.js +101 -0
- package/src/modules/ui-utilities.js +284 -0
- package/src/modules/warlock-invocations.js +219 -0
- package/src/modules/window-management.js +211 -0
- package/src/render/character.ts +234 -0
- package/src/render/h.ts +74 -0
- package/src/render/index.ts +10 -0
- package/src/render/mount.ts +94 -0
- package/src/supabase/client.js +1383 -0
- package/src/supabase/config.js +60 -0
- package/src/supabase/fields.ts +129 -0
- package/src/types/character.ts +85 -0
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Spell Macros Module
|
|
3
|
+
*
|
|
4
|
+
* Handles custom macro system for spells.
|
|
5
|
+
* - Get/save custom macros from localStorage
|
|
6
|
+
* - Configure custom macro buttons modal
|
|
7
|
+
* - Allows spells to have custom Roll20 macro buttons
|
|
8
|
+
*
|
|
9
|
+
* Loaded as a plain script (no ES6 modules) to export to globalThis.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
(function() {
|
|
13
|
+
'use strict';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Get custom macros for a spell from localStorage
|
|
17
|
+
* @param {string} spellName - Name of the spell
|
|
18
|
+
* @returns {object|null} Custom macros object or null
|
|
19
|
+
*/
|
|
20
|
+
function getCustomMacros(spellName) {
|
|
21
|
+
const key = `customMacros_${characterData.name}`;
|
|
22
|
+
const allMacros = JSON.parse(localStorage.getItem(key) || '{}');
|
|
23
|
+
return allMacros[spellName] || null;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Save custom macros for a spell to localStorage
|
|
28
|
+
* @param {string} spellName - Name of the spell
|
|
29
|
+
* @param {object|null} macros - Custom macros object or null to clear
|
|
30
|
+
*/
|
|
31
|
+
function saveCustomMacros(spellName, macros) {
|
|
32
|
+
const key = `customMacros_${characterData.name}`;
|
|
33
|
+
const allMacros = JSON.parse(localStorage.getItem(key) || '{}');
|
|
34
|
+
|
|
35
|
+
if (macros && macros.buttons && macros.buttons.length > 0) {
|
|
36
|
+
allMacros[spellName] = macros;
|
|
37
|
+
} else {
|
|
38
|
+
delete allMacros[spellName]; // Remove if no macros defined
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
localStorage.setItem(key, JSON.stringify(allMacros));
|
|
42
|
+
|
|
43
|
+
const debug = window.debug || console;
|
|
44
|
+
debug.log(`💾 Saved custom macros for "${spellName}":`, macros);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Show custom macro configuration modal
|
|
49
|
+
* @param {object} spell - Spell object
|
|
50
|
+
* @param {number} spellIndex - Spell index
|
|
51
|
+
*/
|
|
52
|
+
function showCustomMacroModal(spell, spellIndex) {
|
|
53
|
+
const overlay = document.createElement('div');
|
|
54
|
+
overlay.style.cssText = 'position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0,0,0,0.7); display: flex; align-items: center; justify-content: center; z-index: 10000;';
|
|
55
|
+
|
|
56
|
+
const modal = document.createElement('div');
|
|
57
|
+
modal.style.cssText = 'background: var(--bg-secondary); color: var(--text-primary); padding: 24px; border-radius: 8px; max-width: 600px; width: 90%; max-height: 80vh; overflow-y: auto; box-shadow: 0 4px 20px rgba(0,0,0,0.3);';
|
|
58
|
+
|
|
59
|
+
const existingMacros = getCustomMacros(spell.name);
|
|
60
|
+
const skipNormalButtons = existingMacros?.skipNormalButtons || false;
|
|
61
|
+
|
|
62
|
+
modal.innerHTML = `
|
|
63
|
+
<h2 style="margin: 0 0 16px 0; color: #333;">Custom Macros: ${spell.name}</h2>
|
|
64
|
+
<p style="margin: 0 0 16px 0; color: #666; font-size: 14px;">
|
|
65
|
+
Configure custom macro buttons for this spell. Use this for magic item spells or custom variants that don't work with the default buttons.
|
|
66
|
+
</p>
|
|
67
|
+
|
|
68
|
+
<div style="margin-bottom: 16px;">
|
|
69
|
+
<label style="display: flex; align-items: center; gap: 8px; cursor: pointer;">
|
|
70
|
+
<input type="checkbox" id="skipNormalButtons" ${skipNormalButtons ? 'checked' : ''} style="width: 18px; height: 18px;">
|
|
71
|
+
<span style="font-weight: bold;">Replace default buttons (hide attack/damage buttons)</span>
|
|
72
|
+
</label>
|
|
73
|
+
<p style="margin: 4px 0 0 26px; color: #666; font-size: 13px;">
|
|
74
|
+
Check this to only show your custom macros, hiding the default spell buttons
|
|
75
|
+
</p>
|
|
76
|
+
</div>
|
|
77
|
+
|
|
78
|
+
<div id="macro-buttons-container" style="margin-bottom: 16px;">
|
|
79
|
+
<!-- Macro buttons will be added here -->
|
|
80
|
+
</div>
|
|
81
|
+
|
|
82
|
+
<button id="add-macro-btn" style="padding: 8px 16px; background: #27ae60; color: white; border: none; border-radius: 4px; cursor: pointer; font-weight: bold; margin-bottom: 16px;">
|
|
83
|
+
➕ Add Macro Button
|
|
84
|
+
</button>
|
|
85
|
+
|
|
86
|
+
<div style="margin-top: 24px; padding-top: 16px; border-top: 2px solid #eee; display: flex; gap: 12px; justify-content: flex-end;">
|
|
87
|
+
<button id="clear-macros-btn" style="padding: 10px 20px; background: #e74c3c; color: white; border: none; border-radius: 6px; cursor: pointer; font-weight: bold;">
|
|
88
|
+
🗑️ Clear All
|
|
89
|
+
</button>
|
|
90
|
+
<button id="cancel-macros-btn" style="padding: 10px 20px; background: #95a5a6; color: white; border: none; border-radius: 6px; cursor: pointer; font-weight: bold;">
|
|
91
|
+
Cancel
|
|
92
|
+
</button>
|
|
93
|
+
<button id="save-macros-btn" style="padding: 10px 20px; background: #3498db; color: white; border: none; border-radius: 6px; cursor: pointer; font-weight: bold;">
|
|
94
|
+
💾 Save
|
|
95
|
+
</button>
|
|
96
|
+
</div>
|
|
97
|
+
`;
|
|
98
|
+
|
|
99
|
+
overlay.appendChild(modal);
|
|
100
|
+
document.body.appendChild(overlay);
|
|
101
|
+
|
|
102
|
+
const container = modal.querySelector('#macro-buttons-container');
|
|
103
|
+
const addBtn = modal.querySelector('#add-macro-btn');
|
|
104
|
+
const clearBtn = modal.querySelector('#clear-macros-btn');
|
|
105
|
+
const cancelBtn = modal.querySelector('#cancel-macros-btn');
|
|
106
|
+
const saveBtn = modal.querySelector('#save-macros-btn');
|
|
107
|
+
|
|
108
|
+
let macroCounter = 0;
|
|
109
|
+
|
|
110
|
+
function addMacroButton(label = '', macro = '') {
|
|
111
|
+
const macroDiv = document.createElement('div');
|
|
112
|
+
macroDiv.className = 'macro-button-config';
|
|
113
|
+
macroDiv.style.cssText = 'padding: 12px; background: #f8f9fa; border-radius: 6px; margin-bottom: 12px; border: 2px solid #dee2e6;';
|
|
114
|
+
macroDiv.dataset.macroId = macroCounter++;
|
|
115
|
+
|
|
116
|
+
macroDiv.innerHTML = `
|
|
117
|
+
<div style="margin-bottom: 8px;">
|
|
118
|
+
<label style="display: block; font-weight: bold; margin-bottom: 4px; color: #333;">Button Label:</label>
|
|
119
|
+
<input type="text" class="macro-label" value="${label}" placeholder="e.g., ⚔️ Attack, 💥 Damage, ✨ Cast" style="width: 100%; padding: 8px; border: 2px solid #ddd; border-radius: 4px; font-size: 14px;">
|
|
120
|
+
</div>
|
|
121
|
+
<div style="margin-bottom: 8px;">
|
|
122
|
+
<label style="display: block; font-weight: bold; margin-bottom: 4px; color: #333;">Macro Text:</label>
|
|
123
|
+
<textarea class="macro-text" placeholder="&{template:default} {{name=My Spell}} {{effect=Custom effect}}" style="width: 100%; padding: 8px; border: 2px solid #ddd; border-radius: 4px; font-size: 13px; font-family: monospace; min-height: 80px;">${macro}</textarea>
|
|
124
|
+
</div>
|
|
125
|
+
<button class="remove-macro-btn" style="padding: 6px 12px; background: #e74c3c; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 12px;">
|
|
126
|
+
❌ Remove
|
|
127
|
+
</button>
|
|
128
|
+
`;
|
|
129
|
+
|
|
130
|
+
const removeBtn = macroDiv.querySelector('.remove-macro-btn');
|
|
131
|
+
removeBtn.addEventListener('click', () => {
|
|
132
|
+
macroDiv.remove();
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
container.appendChild(macroDiv);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Add existing macros or one empty macro
|
|
139
|
+
if (existingMacros && existingMacros.buttons && existingMacros.buttons.length > 0) {
|
|
140
|
+
existingMacros.buttons.forEach(btn => {
|
|
141
|
+
addMacroButton(btn.label, btn.macro);
|
|
142
|
+
});
|
|
143
|
+
} else {
|
|
144
|
+
addMacroButton();
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
addBtn.addEventListener('click', () => addMacroButton());
|
|
148
|
+
|
|
149
|
+
clearBtn.addEventListener('click', () => {
|
|
150
|
+
if (confirm(`Clear all custom macros for "${spell.name}"?`)) {
|
|
151
|
+
saveCustomMacros(spell.name, null);
|
|
152
|
+
document.body.removeChild(overlay);
|
|
153
|
+
if (typeof showNotification === 'function') {
|
|
154
|
+
showNotification(`🗑️ Cleared custom macros for ${spell.name}`, 'success');
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
cancelBtn.addEventListener('click', () => {
|
|
160
|
+
document.body.removeChild(overlay);
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
saveBtn.addEventListener('click', () => {
|
|
164
|
+
const macroConfigs = Array.from(container.querySelectorAll('.macro-button-config'));
|
|
165
|
+
const buttons = macroConfigs.map(config => {
|
|
166
|
+
const label = config.querySelector('.macro-label').value.trim();
|
|
167
|
+
const macro = config.querySelector('.macro-text').value.trim();
|
|
168
|
+
return { label, macro };
|
|
169
|
+
}).filter(btn => btn.label && btn.macro); // Only save if both label and macro are provided
|
|
170
|
+
|
|
171
|
+
const skipNormalButtons = modal.querySelector('#skipNormalButtons').checked;
|
|
172
|
+
|
|
173
|
+
saveCustomMacros(spell.name, {
|
|
174
|
+
buttons,
|
|
175
|
+
skipNormalButtons
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
document.body.removeChild(overlay);
|
|
179
|
+
if (typeof showNotification === 'function') {
|
|
180
|
+
showNotification(`💾 Saved custom macros for ${spell.name}`, 'success');
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
// Close on overlay click
|
|
185
|
+
overlay.addEventListener('click', (e) => {
|
|
186
|
+
if (e.target === overlay) {
|
|
187
|
+
document.body.removeChild(overlay);
|
|
188
|
+
}
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// Export functions to globalThis
|
|
193
|
+
Object.assign(globalThis, {
|
|
194
|
+
getCustomMacros,
|
|
195
|
+
saveCustomMacros,
|
|
196
|
+
showCustomMacroModal
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
console.log('✅ Spell Macros module loaded');
|
|
200
|
+
|
|
201
|
+
})();
|