@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,242 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Inventory Manager Module
|
|
3
|
+
*
|
|
4
|
+
* Handles inventory display and item card creation.
|
|
5
|
+
* Loaded as a plain script (no ES6 modules) to export to window.
|
|
6
|
+
*
|
|
7
|
+
* Functions exported to globalThis:
|
|
8
|
+
* - rebuildInventory()
|
|
9
|
+
* - buildInventoryDisplay(container, inventory)
|
|
10
|
+
* - createInventoryCard(item)
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
(function() {
|
|
14
|
+
'use strict';
|
|
15
|
+
|
|
16
|
+
// Inventory filter state (global so popup-sheet.js can update it)
|
|
17
|
+
if (!globalThis.inventoryFilters) {
|
|
18
|
+
globalThis.inventoryFilters = {
|
|
19
|
+
filter: 'equipped', // 'all', 'equipped', 'attuned', 'container'
|
|
20
|
+
search: ''
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
const inventoryFilters = globalThis.inventoryFilters;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Rebuild inventory display with current character data
|
|
27
|
+
*/
|
|
28
|
+
function rebuildInventory() {
|
|
29
|
+
if (!characterData || !characterData.inventory) return;
|
|
30
|
+
const container = document.getElementById('inventory-container');
|
|
31
|
+
buildInventoryDisplay(container, characterData.inventory);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Build and display inventory with filtering
|
|
36
|
+
*/
|
|
37
|
+
function buildInventoryDisplay(container, inventory) {
|
|
38
|
+
// Clear container
|
|
39
|
+
container.innerHTML = '';
|
|
40
|
+
|
|
41
|
+
// Update currency display in header
|
|
42
|
+
// updateInventoryCurrencyDisplay(inventory); // Commented out currency viewer
|
|
43
|
+
|
|
44
|
+
if (!inventory || inventory.length === 0) {
|
|
45
|
+
container.innerHTML = '<p style="color: var(--text-secondary); text-align: center; padding: 20px;">No items in inventory</p>';
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
debug.log(`🎒 Building inventory display with ${inventory.length} items`);
|
|
50
|
+
|
|
51
|
+
// Apply filters
|
|
52
|
+
let filteredInventory = inventory.filter(item => {
|
|
53
|
+
// Filter out coins (currency) - they're tracked separately
|
|
54
|
+
const lowerName = (item.name || '').toLowerCase();
|
|
55
|
+
const coinPatterns = ['platinum piece', 'gold piece', 'silver piece', 'copper piece', 'electrum piece',
|
|
56
|
+
'platinum coin', 'gold coin', 'silver coin', 'copper coin', 'electrum coin',
|
|
57
|
+
'pp', 'gp', 'sp', 'cp', 'ep'];
|
|
58
|
+
// Check for exact matches or plurals
|
|
59
|
+
const isCoin = coinPatterns.some(pattern => {
|
|
60
|
+
if (pattern.length <= 2) {
|
|
61
|
+
// Short patterns (pp, gp, etc.) - match exactly or with quantity prefix
|
|
62
|
+
return lowerName === pattern || lowerName === pattern + 's' || lowerName.match(new RegExp(`^\\d+\\s*${pattern}s?$`));
|
|
63
|
+
}
|
|
64
|
+
// Longer patterns - match if name contains it
|
|
65
|
+
return lowerName.includes(pattern);
|
|
66
|
+
});
|
|
67
|
+
if (isCoin) {
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Filter by type
|
|
72
|
+
if (inventoryFilters.filter === 'equipped' && !item.equipped) {
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
if (inventoryFilters.filter === 'attuned' && !item.attuned) {
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
if (inventoryFilters.filter === 'container' && item.type !== 'container') {
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Filter by search term
|
|
83
|
+
if (inventoryFilters.search) {
|
|
84
|
+
const searchLower = inventoryFilters.search;
|
|
85
|
+
const name = (item.name || '').toLowerCase();
|
|
86
|
+
const desc = (item.description || '').toLowerCase();
|
|
87
|
+
const tagsString = (item.tags || []).join(' ').toLowerCase();
|
|
88
|
+
if (!name.includes(searchLower) && !desc.includes(searchLower) && !tagsString.includes(searchLower)) {
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return true;
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
if (filteredInventory.length === 0) {
|
|
97
|
+
container.innerHTML = '<p style="color: var(--text-secondary); text-align: center; padding: 20px;">No items match filters</p>';
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Sort inventory: equipped first, then by name
|
|
102
|
+
filteredInventory.sort((a, b) => {
|
|
103
|
+
if (a.equipped && !b.equipped) return -1;
|
|
104
|
+
if (!a.equipped && b.equipped) return 1;
|
|
105
|
+
return (a.name || '').localeCompare(b.name || '');
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
// Group items by category/container
|
|
109
|
+
filteredInventory.forEach(item => {
|
|
110
|
+
const itemCard = createInventoryCard(item);
|
|
111
|
+
container.appendChild(itemCard);
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
debug.log(`✅ Inventory display built with ${filteredInventory.length} items`);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Create an inventory item card element
|
|
119
|
+
*/
|
|
120
|
+
function createInventoryCard(item) {
|
|
121
|
+
const card = document.createElement('div');
|
|
122
|
+
card.className = 'action-card'; // Reuse action card styling
|
|
123
|
+
card.style.cssText = `
|
|
124
|
+
background: var(--bg-card);
|
|
125
|
+
border-left: 4px solid ${item.equipped ? '#27ae60' : item.attuned ? '#9b59b6' : '#95a5a6'};
|
|
126
|
+
padding: 15px;
|
|
127
|
+
margin-bottom: 10px;
|
|
128
|
+
border-radius: 6px;
|
|
129
|
+
cursor: pointer;
|
|
130
|
+
transition: all 0.2s;
|
|
131
|
+
${item.equipped ? 'box-shadow: 0 0 10px rgba(39, 174, 96, 0.3);' : ''}
|
|
132
|
+
`;
|
|
133
|
+
|
|
134
|
+
card.onmouseover = () => {
|
|
135
|
+
card.style.background = 'var(--bg-card-hover)';
|
|
136
|
+
card.style.transform = 'translateX(2px)';
|
|
137
|
+
};
|
|
138
|
+
card.onmouseout = () => {
|
|
139
|
+
card.style.background = 'var(--bg-card)';
|
|
140
|
+
card.style.transform = 'translateX(0)';
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
// Header with name and quantity
|
|
144
|
+
const header = document.createElement('div');
|
|
145
|
+
header.style.cssText = 'display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px;';
|
|
146
|
+
|
|
147
|
+
const nameSection = document.createElement('div');
|
|
148
|
+
nameSection.style.cssText = 'display: flex; align-items: center; gap: 8px;';
|
|
149
|
+
|
|
150
|
+
const itemName = document.createElement('strong');
|
|
151
|
+
itemName.textContent = item.name || 'Unnamed Item';
|
|
152
|
+
itemName.style.cssText = 'color: var(--text-primary); font-size: 1.1em;';
|
|
153
|
+
nameSection.appendChild(itemName);
|
|
154
|
+
|
|
155
|
+
// Add badges for equipped/attuned
|
|
156
|
+
if (item.equipped) {
|
|
157
|
+
const equippedBadge = document.createElement('span');
|
|
158
|
+
equippedBadge.textContent = '⚔️ Equipped';
|
|
159
|
+
equippedBadge.style.cssText = 'background: #27ae60; color: white; padding: 2px 8px; border-radius: 12px; font-size: 0.75em; font-weight: bold;';
|
|
160
|
+
nameSection.appendChild(equippedBadge);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
if (item.attuned) {
|
|
164
|
+
const attunedBadge = document.createElement('span');
|
|
165
|
+
attunedBadge.textContent = '✨ Attuned';
|
|
166
|
+
attunedBadge.style.cssText = 'background: #9b59b6; color: white; padding: 2px 8px; border-radius: 12px; font-size: 0.75em; font-weight: bold;';
|
|
167
|
+
nameSection.appendChild(attunedBadge);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
if (item.requiresAttunement && !item.attuned) {
|
|
171
|
+
const requiresBadge = document.createElement('span');
|
|
172
|
+
requiresBadge.textContent = '(Requires Attunement)';
|
|
173
|
+
requiresBadge.style.cssText = 'color: var(--text-muted); font-size: 0.85em; font-style: italic;';
|
|
174
|
+
nameSection.appendChild(requiresBadge);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
header.appendChild(nameSection);
|
|
178
|
+
|
|
179
|
+
// Quantity display
|
|
180
|
+
const metaSection = document.createElement('div');
|
|
181
|
+
metaSection.style.cssText = 'display: flex; flex-direction: column; align-items: flex-end; gap: 4px;';
|
|
182
|
+
|
|
183
|
+
if (item.quantity > 1 || item.showIncrement) {
|
|
184
|
+
const quantitySpan = document.createElement('span');
|
|
185
|
+
quantitySpan.textContent = `×${item.quantity}`;
|
|
186
|
+
quantitySpan.style.cssText = 'color: var(--text-secondary); font-weight: bold; font-size: 1.1em;';
|
|
187
|
+
metaSection.appendChild(quantitySpan);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
header.appendChild(metaSection);
|
|
191
|
+
card.appendChild(header);
|
|
192
|
+
|
|
193
|
+
// Weight
|
|
194
|
+
if (item.weight && item.weight > 0) {
|
|
195
|
+
const weightDiv = document.createElement('div');
|
|
196
|
+
const totalWeight = item.weight * item.quantity;
|
|
197
|
+
weightDiv.textContent = `⚖️ ${totalWeight} lb${totalWeight !== 1 ? 's' : ''}`;
|
|
198
|
+
weightDiv.style.cssText = 'color: var(--text-secondary); font-size: 0.85em; margin-bottom: 4px;';
|
|
199
|
+
card.appendChild(weightDiv);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// Tags
|
|
203
|
+
if (item.tags && item.tags.length > 0) {
|
|
204
|
+
const tagsDiv = document.createElement('div');
|
|
205
|
+
tagsDiv.style.cssText = 'display: flex; gap: 6px; flex-wrap: wrap; margin: 6px 0;';
|
|
206
|
+
item.tags.forEach(tag => {
|
|
207
|
+
const tagSpan = document.createElement('span');
|
|
208
|
+
tagSpan.textContent = tag;
|
|
209
|
+
tagSpan.style.cssText = 'background: var(--bg-tertiary); color: var(--text-secondary); padding: 2px 6px; border-radius: 8px; font-size: 0.75em;';
|
|
210
|
+
tagsDiv.appendChild(tagSpan);
|
|
211
|
+
});
|
|
212
|
+
card.appendChild(tagsDiv);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// Description (collapsed by default, click to expand)
|
|
216
|
+
if (item.description && item.description.trim()) {
|
|
217
|
+
const descDiv = document.createElement('div');
|
|
218
|
+
descDiv.style.cssText = 'color: var(--text-secondary); font-size: 0.9em; margin-top: 8px; border-top: 1px solid var(--border-color); padding-top: 8px; line-height: 1.4; max-height: 0; overflow: hidden; transition: max-height 0.3s;';
|
|
219
|
+
descDiv.innerHTML = item.description.replace(/\n/g, '<br>');
|
|
220
|
+
|
|
221
|
+
card.addEventListener('click', () => {
|
|
222
|
+
if (descDiv.style.maxHeight === '0px' || !descDiv.style.maxHeight) {
|
|
223
|
+
descDiv.style.maxHeight = '500px';
|
|
224
|
+
descDiv.style.paddingTop = '8px';
|
|
225
|
+
} else {
|
|
226
|
+
descDiv.style.maxHeight = '0px';
|
|
227
|
+
descDiv.style.paddingTop = '0px';
|
|
228
|
+
}
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
card.appendChild(descDiv);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
return card;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// Export to globalThis for use across all scripts
|
|
238
|
+
window.rebuildInventory = rebuildInventory;
|
|
239
|
+
window.buildInventoryDisplay = buildInventoryDisplay;
|
|
240
|
+
window.createInventoryCard = createInventoryCard;
|
|
241
|
+
|
|
242
|
+
})();
|