intelligent-system-design-language 0.3.13
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/.claude/agents/langium-language-designer.md +38 -0
- package/.claude/agents/typescript-vscode-expert.md +29 -0
- package/.claude/agents/ui-ux-designer.md +36 -0
- package/.claude/settings.local.json +33 -0
- package/.idea/inspectionProfiles/Project_Default.xml +7 -0
- package/.idea/isdl.iml +14 -0
- package/.idea/modules.xml +9 -0
- package/.idea/vcs.xml +7 -0
- package/.idea/watcherTasks.xml +4 -0
- package/.vscodeignore +18 -0
- package/LICENSE +674 -0
- package/README.md +86 -0
- package/bin/cli.js +4 -0
- package/bin/lsp.js +8 -0
- package/isdl.png +0 -0
- package/out/_backgrounds.scss +91 -0
- package/out/_handlebars.scss +505 -0
- package/out/_isdlStyles.scss +1357 -0
- package/out/_vuetifyOverrides.scss +425 -0
- package/out/_vuetifyStyles.scss +31957 -0
- package/out/cli/cli-util.js +39 -0
- package/out/cli/cli-util.js.map +1 -0
- package/out/cli/components/_backgrounds.scss +91 -0
- package/out/cli/components/_handlebars.scss +505 -0
- package/out/cli/components/_isdlStyles.scss +1357 -0
- package/out/cli/components/_vuetifyOverrides.scss +425 -0
- package/out/cli/components/_vuetifyStyles.scss +31957 -0
- package/out/cli/components/active-effect-sheet-generator.js +643 -0
- package/out/cli/components/active-effect-sheet-generator.js.map +1 -0
- package/out/cli/components/base-actor-sheet-generator.js +125 -0
- package/out/cli/components/base-actor-sheet-generator.js.map +1 -0
- package/out/cli/components/base-sheet-generator.js +525 -0
- package/out/cli/components/base-sheet-generator.js.map +1 -0
- package/out/cli/components/chat-card-generator.js +683 -0
- package/out/cli/components/chat-card-generator.js.map +1 -0
- package/out/cli/components/css-generator.js +58 -0
- package/out/cli/components/css-generator.js.map +1 -0
- package/out/cli/components/damage-roll-generator.js +173 -0
- package/out/cli/components/damage-roll-generator.js.map +1 -0
- package/out/cli/components/datamodel-generator.js +672 -0
- package/out/cli/components/datamodel-generator.js.map +1 -0
- package/out/cli/components/derived-data-generator.js +1340 -0
- package/out/cli/components/derived-data-generator.js.map +1 -0
- package/out/cli/components/hotbar-drop-hook-generator.js +95 -0
- package/out/cli/components/hotbar-drop-hook-generator.js.map +1 -0
- package/out/cli/components/init-hook-generator.js +597 -0
- package/out/cli/components/init-hook-generator.js.map +1 -0
- package/out/cli/components/keywords-generator.js +220 -0
- package/out/cli/components/keywords-generator.js.map +1 -0
- package/out/cli/components/language-generator.js +110 -0
- package/out/cli/components/language-generator.js.map +1 -0
- package/out/cli/components/measured-template-preview.js +234 -0
- package/out/cli/components/measured-template-preview.js.map +1 -0
- package/out/cli/components/method-generator.js +1812 -0
- package/out/cli/components/method-generator.js.map +1 -0
- package/out/cli/components/ready-hook-generator.js +448 -0
- package/out/cli/components/ready-hook-generator.js.map +1 -0
- package/out/cli/components/token-generator.js +138 -0
- package/out/cli/components/token-generator.js.map +1 -0
- package/out/cli/components/utils.js +176 -0
- package/out/cli/components/utils.js.map +1 -0
- package/out/cli/components/vue/base-components/vue-attribute.js +148 -0
- package/out/cli/components/vue/base-components/vue-attribute.js.map +1 -0
- package/out/cli/components/vue/base-components/vue-boolean.js +77 -0
- package/out/cli/components/vue/base-components/vue-boolean.js.map +1 -0
- package/out/cli/components/vue/base-components/vue-calculator.js +106 -0
- package/out/cli/components/vue/base-components/vue-calculator.js.map +1 -0
- package/out/cli/components/vue/base-components/vue-damage-application.js +369 -0
- package/out/cli/components/vue/base-components/vue-damage-application.js.map +1 -0
- package/out/cli/components/vue/base-components/vue-damage-bonuses.js +225 -0
- package/out/cli/components/vue/base-components/vue-damage-bonuses.js.map +1 -0
- package/out/cli/components/vue/base-components/vue-damage-resistances.js +256 -0
- package/out/cli/components/vue/base-components/vue-damage-resistances.js.map +1 -0
- package/out/cli/components/vue/base-components/vue-damage-track.js +134 -0
- package/out/cli/components/vue/base-components/vue-damage-track.js.map +1 -0
- package/out/cli/components/vue/base-components/vue-date-time.js +55 -0
- package/out/cli/components/vue/base-components/vue-date-time.js.map +1 -0
- package/out/cli/components/vue/base-components/vue-dice.js +111 -0
- package/out/cli/components/vue/base-components/vue-dice.js.map +1 -0
- package/out/cli/components/vue/base-components/vue-die.js +86 -0
- package/out/cli/components/vue/base-components/vue-die.js.map +1 -0
- package/out/cli/components/vue/base-components/vue-document-choice.js +172 -0
- package/out/cli/components/vue/base-components/vue-document-choice.js.map +1 -0
- package/out/cli/components/vue/base-components/vue-document-choices.js +203 -0
- package/out/cli/components/vue/base-components/vue-document-choices.js.map +1 -0
- package/out/cli/components/vue/base-components/vue-document-link.js +73 -0
- package/out/cli/components/vue/base-components/vue-document-link.js.map +1 -0
- package/out/cli/components/vue/base-components/vue-extended-choice.js +101 -0
- package/out/cli/components/vue/base-components/vue-extended-choice.js.map +1 -0
- package/out/cli/components/vue/base-components/vue-inventory.js +532 -0
- package/out/cli/components/vue/base-components/vue-inventory.js.map +1 -0
- package/out/cli/components/vue/base-components/vue-macro-choice.js +150 -0
- package/out/cli/components/vue/base-components/vue-macro-choice.js.map +1 -0
- package/out/cli/components/vue/base-components/vue-measured-template.js +543 -0
- package/out/cli/components/vue/base-components/vue-measured-template.js.map +1 -0
- package/out/cli/components/vue/base-components/vue-money.js +496 -0
- package/out/cli/components/vue/base-components/vue-money.js.map +1 -0
- package/out/cli/components/vue/base-components/vue-number.js +184 -0
- package/out/cli/components/vue/base-components/vue-number.js.map +1 -0
- package/out/cli/components/vue/base-components/vue-paperdoll.js +56 -0
- package/out/cli/components/vue/base-components/vue-paperdoll.js.map +1 -0
- package/out/cli/components/vue/base-components/vue-parent-property-reference.js +89 -0
- package/out/cli/components/vue/base-components/vue-parent-property-reference.js.map +1 -0
- package/out/cli/components/vue/base-components/vue-prosemirror.js +31 -0
- package/out/cli/components/vue/base-components/vue-prosemirror.js.map +1 -0
- package/out/cli/components/vue/base-components/vue-resource.js +149 -0
- package/out/cli/components/vue/base-components/vue-resource.js.map +1 -0
- package/out/cli/components/vue/base-components/vue-roll-visualizer.js +121 -0
- package/out/cli/components/vue/base-components/vue-roll-visualizer.js.map +1 -0
- package/out/cli/components/vue/base-components/vue-self-property-reference.js +75 -0
- package/out/cli/components/vue/base-components/vue-self-property-reference.js.map +1 -0
- package/out/cli/components/vue/base-components/vue-string-choice.js +111 -0
- package/out/cli/components/vue/base-components/vue-string-choice.js.map +1 -0
- package/out/cli/components/vue/base-components/vue-string-choices.js +216 -0
- package/out/cli/components/vue/base-components/vue-string-choices.js.map +1 -0
- package/out/cli/components/vue/base-components/vue-string.js +73 -0
- package/out/cli/components/vue/base-components/vue-string.js.map +1 -0
- package/out/cli/components/vue/base-components/vue-text-field.js +66 -0
- package/out/cli/components/vue/base-components/vue-text-field.js.map +1 -0
- package/out/cli/components/vue/base-components/vue-tracker.js +444 -0
- package/out/cli/components/vue/base-components/vue-tracker.js.map +1 -0
- package/out/cli/components/vue/vue-action-component-generator.js +88 -0
- package/out/cli/components/vue/vue-action-component-generator.js.map +1 -0
- package/out/cli/components/vue/vue-active-effect-sheet-generator.js +1016 -0
- package/out/cli/components/vue/vue-active-effect-sheet-generator.js.map +1 -0
- package/out/cli/components/vue/vue-base-components-generator.js +59 -0
- package/out/cli/components/vue/vue-base-components-generator.js.map +1 -0
- package/out/cli/components/vue/vue-datatable-component-generator.js +307 -0
- package/out/cli/components/vue/vue-datatable-component-generator.js.map +1 -0
- package/out/cli/components/vue/vue-datatable-sheet-class-generator.js +342 -0
- package/out/cli/components/vue/vue-datatable-sheet-class-generator.js.map +1 -0
- package/out/cli/components/vue/vue-datatable2-component-generator.js +939 -0
- package/out/cli/components/vue/vue-datatable2-component-generator.js.map +1 -0
- package/out/cli/components/vue/vue-document-creation-app.js +140 -0
- package/out/cli/components/vue/vue-document-creation-app.js.map +1 -0
- package/out/cli/components/vue/vue-document-creation-sheet.js +105 -0
- package/out/cli/components/vue/vue-document-creation-sheet.js.map +1 -0
- package/out/cli/components/vue/vue-generator.js +240 -0
- package/out/cli/components/vue/vue-generator.js.map +1 -0
- package/out/cli/components/vue/vue-mixin.js +338 -0
- package/out/cli/components/vue/vue-mixin.js.map +1 -0
- package/out/cli/components/vue/vue-pinned-datatable-component-generator.js +306 -0
- package/out/cli/components/vue/vue-pinned-datatable-component-generator.js.map +1 -0
- package/out/cli/components/vue/vue-prompt-generator.js +201 -0
- package/out/cli/components/vue/vue-prompt-generator.js.map +1 -0
- package/out/cli/components/vue/vue-prompt-sheet-class-generator.js +252 -0
- package/out/cli/components/vue/vue-prompt-sheet-class-generator.js.map +1 -0
- package/out/cli/components/vue/vue-sheet-application-generator.js +2008 -0
- package/out/cli/components/vue/vue-sheet-application-generator.js.map +1 -0
- package/out/cli/components/vue/vue-sheet-class-generator.js +484 -0
- package/out/cli/components/vue/vue-sheet-class-generator.js.map +1 -0
- package/out/cli/generator.js +659 -0
- package/out/cli/generator.js.map +1 -0
- package/out/cli/main.js +43 -0
- package/out/cli/main.js.map +1 -0
- package/out/datatables.min.css +54 -0
- package/out/datatables.min.js +178 -0
- package/out/extension/github/githubAuthProvider.js +345 -0
- package/out/extension/github/githubAuthProvider.js.map +1 -0
- package/out/extension/github/githubConfig.js +132 -0
- package/out/extension/github/githubConfig.js.map +1 -0
- package/out/extension/github/githubGistActions.js +251 -0
- package/out/extension/github/githubGistActions.js.map +1 -0
- package/out/extension/github/githubGistManager.js +255 -0
- package/out/extension/github/githubGistManager.js.map +1 -0
- package/out/extension/github/githubManager.js +1735 -0
- package/out/extension/github/githubManager.js.map +1 -0
- package/out/extension/github/githubQuickActions.js +659 -0
- package/out/extension/github/githubQuickActions.js.map +1 -0
- package/out/extension/github/githubTreeProvider.js +181 -0
- package/out/extension/github/githubTreeProvider.js.map +1 -0
- package/out/extension/github/system-workflow.yml +48 -0
- package/out/extension/main.cjs +70315 -0
- package/out/extension/main.cjs.map +7 -0
- package/out/extension/main.js +237 -0
- package/out/extension/main.js.map +1 -0
- package/out/extension/package.json +426 -0
- package/out/isdl.png +0 -0
- package/out/language/generated/ast.js +2992 -0
- package/out/language/generated/ast.js.map +1 -0
- package/out/language/generated/grammar.js +13970 -0
- package/out/language/generated/grammar.js.map +1 -0
- package/out/language/generated/module.js +20 -0
- package/out/language/generated/module.js.map +1 -0
- package/out/language/intelligent-system-design-language-formatter.js +85 -0
- package/out/language/intelligent-system-design-language-formatter.js.map +1 -0
- package/out/language/intelligent-system-design-language-module.js +69 -0
- package/out/language/intelligent-system-design-language-module.js.map +1 -0
- package/out/language/intelligent-system-design-language-quickfixes.js +37 -0
- package/out/language/intelligent-system-design-language-quickfixes.js.map +1 -0
- package/out/language/intelligent-system-design-language-validator.js +515 -0
- package/out/language/intelligent-system-design-language-validator.js.map +1 -0
- package/out/language/isdl-hover-provider.js +77 -0
- package/out/language/isdl-hover-provider.js.map +1 -0
- package/out/language/isdl-scope-provider.js +149 -0
- package/out/language/isdl-scope-provider.js.map +1 -0
- package/out/language/main.cjs +47655 -0
- package/out/language/main.cjs.map +7 -0
- package/out/language/main.js +11 -0
- package/out/language/main.js.map +1 -0
- package/out/missing-character.png +0 -0
- package/out/package.json +426 -0
- package/out/paperdoll_default.png +0 -0
- package/out/progressbar.min.js +7 -0
- package/out/styles.scss +722 -0
- package/out/test/formatting/formatter.test.js +46 -0
- package/out/test/formatting/formatter.test.js.map +1 -0
- package/out/vuetify.esm.js +30279 -0
- package/package.json +426 -0
|
@@ -0,0 +1,496 @@
|
|
|
1
|
+
import * as path from 'node:path';
|
|
2
|
+
import * as fs from 'node:fs';
|
|
3
|
+
import { expandToNode, toString } from 'langium/generate';
|
|
4
|
+
export default function generateMoneyComponent(destination, entry) {
|
|
5
|
+
const generatedFileDir = path.join(destination, "system", "templates", "vue", "components");
|
|
6
|
+
const generatedFilePath = path.join(generatedFileDir, `money.vue`);
|
|
7
|
+
if (!fs.existsSync(generatedFileDir)) {
|
|
8
|
+
fs.mkdirSync(generatedFileDir, { recursive: true });
|
|
9
|
+
}
|
|
10
|
+
const fileNode = expandToNode `
|
|
11
|
+
<script setup>
|
|
12
|
+
import { ref, computed, inject } from "vue";
|
|
13
|
+
|
|
14
|
+
const props = defineProps({
|
|
15
|
+
label: String,
|
|
16
|
+
systemPath: String,
|
|
17
|
+
context: Object,
|
|
18
|
+
visibility: String,
|
|
19
|
+
editMode: Boolean,
|
|
20
|
+
icon: String,
|
|
21
|
+
color: String,
|
|
22
|
+
disabled: Boolean,
|
|
23
|
+
hasValueParam: Boolean,
|
|
24
|
+
primaryColor: String,
|
|
25
|
+
secondaryColor: String,
|
|
26
|
+
format: {
|
|
27
|
+
type: String,
|
|
28
|
+
default: "auto"
|
|
29
|
+
},
|
|
30
|
+
precision: {
|
|
31
|
+
type: Number,
|
|
32
|
+
default: 1
|
|
33
|
+
},
|
|
34
|
+
display: {
|
|
35
|
+
type: String,
|
|
36
|
+
default: "breakdown"
|
|
37
|
+
},
|
|
38
|
+
denominations: {
|
|
39
|
+
type: Array,
|
|
40
|
+
default: () => []
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
const document = inject("rawDocument");
|
|
45
|
+
|
|
46
|
+
// Vuetify's up/down stepper buttons update the model without firing a
|
|
47
|
+
// native change event, so Foundry's submitOnChange form handler never
|
|
48
|
+
// persists them. When the value changes while focus is NOT on a text
|
|
49
|
+
// input (i.e. a stepper click, not typing), persist directly. Typing
|
|
50
|
+
// still persists via the input's native change on blur/enter.
|
|
51
|
+
// ('document' is the injected Foundry document; DOM access uses window.)
|
|
52
|
+
const persistOnStep = (path, newValue) => {
|
|
53
|
+
if (document && window.document.activeElement?.tagName !== 'INPUT') {
|
|
54
|
+
document.update({ [path]: newValue });
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const isHidden = computed(() => {
|
|
59
|
+
if (props.visibility === "hidden") {
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
if (props.visibility === "gm" && !game.user.isGM) {
|
|
63
|
+
return true;
|
|
64
|
+
}
|
|
65
|
+
return false;
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
const isDisabled = computed(() => {
|
|
69
|
+
return props.disabled ||
|
|
70
|
+
props.hasValueParam ||
|
|
71
|
+
props.visibility === "locked" ||
|
|
72
|
+
props.visibility === "readonly" ||
|
|
73
|
+
(props.visibility === "gmOnly" && !game.user.isGM);
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
const fieldColor = computed(() => {
|
|
77
|
+
return props.color || 'primary';
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
const showDenominationPanel = ref(false);
|
|
81
|
+
const showConversionDialog = ref(false);
|
|
82
|
+
const conversionSource = ref(null);
|
|
83
|
+
const conversionTarget = ref(null);
|
|
84
|
+
const conversionAmount = ref(0);
|
|
85
|
+
|
|
86
|
+
// For single currency, value is just a number
|
|
87
|
+
// For multi-denomination, value is an object: { gold: 1, silver: 25, bronze: 32 }
|
|
88
|
+
const value = computed({
|
|
89
|
+
get: () => foundry.utils.getProperty(props.context, props.systemPath),
|
|
90
|
+
set: (newValue) => {
|
|
91
|
+
// Ensure we always store a valid number for single currency, default to 0 for invalid values
|
|
92
|
+
if (!hasDenominations.value) {
|
|
93
|
+
const validValue = (typeof newValue === 'number' && isFinite(newValue)) ? newValue : 0;
|
|
94
|
+
foundry.utils.setProperty(props.context, props.systemPath, validValue);
|
|
95
|
+
} else {
|
|
96
|
+
foundry.utils.setProperty(props.context, props.systemPath, newValue);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
const hasDenominations = computed(() => {
|
|
102
|
+
return props.denominations && props.denominations.length > 0;
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
// Format a number with k/M/B suffixes
|
|
106
|
+
const formatNumber = (num) => {
|
|
107
|
+
if (props.format === "full") {
|
|
108
|
+
return num.toLocaleString();
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const absNum = Math.abs(num);
|
|
112
|
+
const sign = num < 0 ? '-' : '';
|
|
113
|
+
|
|
114
|
+
// Compact mode: always use fixed precision
|
|
115
|
+
if (props.format === "compact" && absNum >= 1000) {
|
|
116
|
+
if (absNum >= 1000000000) {
|
|
117
|
+
return sign + (absNum / 1000000000).toFixed(props.precision) + 'B';
|
|
118
|
+
}
|
|
119
|
+
if (absNum >= 1000000) {
|
|
120
|
+
return sign + (absNum / 1000000).toFixed(props.precision) + 'M';
|
|
121
|
+
}
|
|
122
|
+
if (absNum >= 1000) {
|
|
123
|
+
return sign + (absNum / 1000).toFixed(props.precision) + 'k';
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Auto mode: dynamically adjust precision to fill field width
|
|
128
|
+
if (props.format === "auto" && absNum >= 1000) {
|
|
129
|
+
const maxChars = 12; // Target character width for the number portion
|
|
130
|
+
let divisor, suffix;
|
|
131
|
+
|
|
132
|
+
if (absNum >= 1000000000) {
|
|
133
|
+
divisor = 1000000000;
|
|
134
|
+
suffix = 'B';
|
|
135
|
+
} else if (absNum >= 1000000) {
|
|
136
|
+
divisor = 1000000;
|
|
137
|
+
suffix = 'M';
|
|
138
|
+
} else {
|
|
139
|
+
divisor = 1000;
|
|
140
|
+
suffix = 'k';
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
const scaledNum = absNum / divisor;
|
|
144
|
+
const integerDigits = Math.floor(scaledNum).toString().length;
|
|
145
|
+
|
|
146
|
+
// Calculate available space: maxChars - sign - integerDigits - decimal point - suffix
|
|
147
|
+
const availableForDecimals = maxChars - sign.length - integerDigits - 1 - suffix.length;
|
|
148
|
+
|
|
149
|
+
// Clamp precision between 0 and available space (max 2 for readability)
|
|
150
|
+
const dynamicPrecision = Math.max(0, Math.min(availableForDecimals, 2));
|
|
151
|
+
|
|
152
|
+
return sign + scaledNum.toFixed(dynamicPrecision) + suffix;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
return num.toLocaleString();
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
// Get total value in base denomination
|
|
159
|
+
const totalValue = computed(() => {
|
|
160
|
+
if (!hasDenominations.value) {
|
|
161
|
+
return value.value || 0;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
let total = 0;
|
|
165
|
+
if (value.value && typeof value.value === 'object') {
|
|
166
|
+
props.denominations.forEach(denom => {
|
|
167
|
+
const denomName = denom.name.toLowerCase();
|
|
168
|
+
const denomValue = value.value[denomName] || 0;
|
|
169
|
+
total += denomValue * (denom.value || 1);
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
return total;
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
// Format display for multi-denomination
|
|
176
|
+
const formattedDenominationDisplay = computed(() => {
|
|
177
|
+
if (!hasDenominations.value || !value.value) return "0";
|
|
178
|
+
|
|
179
|
+
const primary = props.denominations[0];
|
|
180
|
+
const primaryName = primary.name.toLowerCase();
|
|
181
|
+
|
|
182
|
+
if (props.display === "primary") {
|
|
183
|
+
const primaryValue = value.value[primaryName] || 0;
|
|
184
|
+
return \`\${primaryValue}\${primary.name.charAt(0).toLowerCase()}\`;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
if (props.display === "consolidated") {
|
|
188
|
+
const totalInPrimary = totalValue.value / (primary.value || 1);
|
|
189
|
+
return \`\${totalInPrimary.toFixed(2)}\${primary.name.charAt(0).toLowerCase()}\`;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// breakdown
|
|
193
|
+
const parts = [];
|
|
194
|
+
props.denominations.forEach(denom => {
|
|
195
|
+
const denomName = denom.name.toLowerCase();
|
|
196
|
+
const denomValue = value.value[denomName] || 0;
|
|
197
|
+
if (denomValue > 0) {
|
|
198
|
+
parts.push(\`\${denomValue}\${denom.name.charAt(0).toLowerCase()}\`);
|
|
199
|
+
}
|
|
200
|
+
});
|
|
201
|
+
return parts.length > 0 ? parts.join(' ') : '0';
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
const exactAmountTooltip = computed(() => {
|
|
205
|
+
if (!hasDenominations.value) {
|
|
206
|
+
return (value.value || 0).toLocaleString();
|
|
207
|
+
}
|
|
208
|
+
return formattedDenominationDisplay.value;
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
// Formatted display for single currency (used in non-edit mode)
|
|
212
|
+
const formattedSingleDisplay = computed(() => {
|
|
213
|
+
if (hasDenominations.value) return '';
|
|
214
|
+
return formatNumber(value.value || 0);
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
// Single currency edit
|
|
218
|
+
const onSingleCurrencyChange = (newValue) => {
|
|
219
|
+
value.value = newValue;
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
// Multi-denomination edit
|
|
223
|
+
const onDenominationChange = (denomName, newValue) => {
|
|
224
|
+
const current = value.value || {};
|
|
225
|
+
// Ensure we always store a valid number, default to 0 for invalid values
|
|
226
|
+
const validValue = (typeof newValue === 'number' && isFinite(newValue)) ? newValue : 0;
|
|
227
|
+
const updated = { ...current, [denomName]: validValue };
|
|
228
|
+
value.value = updated;
|
|
229
|
+
// Stepper clicks don't fire a native change event; persist directly.
|
|
230
|
+
persistOnStep(\`\${props.systemPath}.\${denomName}\`, validValue);
|
|
231
|
+
};
|
|
232
|
+
|
|
233
|
+
// Open conversion dialog for a specific denomination
|
|
234
|
+
const openConversionDialog = (sourceDenom) => {
|
|
235
|
+
conversionSource.value = sourceDenom;
|
|
236
|
+
// Default to first different denomination
|
|
237
|
+
const otherDenoms = props.denominations.filter(d => d.name !== sourceDenom.name);
|
|
238
|
+
conversionTarget.value = otherDenoms[0] || props.denominations[0];
|
|
239
|
+
conversionAmount.value = 0;
|
|
240
|
+
showConversionDialog.value = true;
|
|
241
|
+
};
|
|
242
|
+
|
|
243
|
+
// Preview the conversion result
|
|
244
|
+
const conversionPreview = computed(() => {
|
|
245
|
+
if (!conversionSource.value || !conversionTarget.value) {
|
|
246
|
+
return { valid: false, result: 0, sourceValue: 0, targetValue: 0 };
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
const sourceName = conversionSource.value.name.toLowerCase();
|
|
250
|
+
const targetName = conversionTarget.value.name.toLowerCase();
|
|
251
|
+
const sourceAvailable = value.value?.[sourceName] || 0;
|
|
252
|
+
const targetAvailable = value.value?.[targetName] || 0;
|
|
253
|
+
|
|
254
|
+
// If no amount specified, just show available amounts
|
|
255
|
+
if (!conversionAmount.value || conversionAmount.value === 0) {
|
|
256
|
+
return { valid: false, result: 0, sourceValue: sourceAvailable, targetValue: targetAvailable };
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// Check if we have enough
|
|
260
|
+
if (conversionAmount.value > sourceAvailable) {
|
|
261
|
+
return { valid: false, result: 0, sourceValue: sourceAvailable, targetValue: targetAvailable, insufficient: true };
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// Calculate conversion
|
|
265
|
+
const sourceValueInBase = conversionAmount.value * conversionSource.value.value;
|
|
266
|
+
const targetResult = Math.floor(sourceValueInBase / conversionTarget.value.value);
|
|
267
|
+
|
|
268
|
+
return {
|
|
269
|
+
valid: targetResult > 0,
|
|
270
|
+
result: targetResult,
|
|
271
|
+
sourceValue: sourceAvailable,
|
|
272
|
+
targetValue: targetAvailable,
|
|
273
|
+
insufficient: false
|
|
274
|
+
};
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
// Execute the conversion
|
|
278
|
+
const executeConversion = () => {
|
|
279
|
+
const preview = conversionPreview.value;
|
|
280
|
+
if (!preview.valid) return;
|
|
281
|
+
|
|
282
|
+
const sourceName = conversionSource.value.name.toLowerCase();
|
|
283
|
+
const targetName = conversionTarget.value.name.toLowerCase();
|
|
284
|
+
|
|
285
|
+
const current = value.value || {};
|
|
286
|
+
const updated = { ...current };
|
|
287
|
+
|
|
288
|
+
updated[sourceName] = (updated[sourceName] || 0) - conversionAmount.value;
|
|
289
|
+
updated[targetName] = (updated[targetName] || 0) + preview.result;
|
|
290
|
+
|
|
291
|
+
value.value = updated;
|
|
292
|
+
showConversionDialog.value = false;
|
|
293
|
+
};
|
|
294
|
+
</script>
|
|
295
|
+
|
|
296
|
+
<template>
|
|
297
|
+
<div v-if="!isHidden" class="isdl-money single-wide">
|
|
298
|
+
<!-- Single Currency Money (Edit Mode) -->
|
|
299
|
+
<v-number-input
|
|
300
|
+
v-if="!hasDenominations && props.editMode"
|
|
301
|
+
:model-value="value"
|
|
302
|
+
@update:model-value="(v) => { value = v; persistOnStep(props.systemPath, v); }"
|
|
303
|
+
:name="props.systemPath"
|
|
304
|
+
:disabled="isDisabled"
|
|
305
|
+
:color="fieldColor"
|
|
306
|
+
controlVariant="stacked"
|
|
307
|
+
density="compact"
|
|
308
|
+
variant="outlined"
|
|
309
|
+
>
|
|
310
|
+
<template #label>
|
|
311
|
+
<span class="field-label">
|
|
312
|
+
<v-icon v-if="props.icon" :icon="props.icon" size="small" class="me-1"></v-icon>
|
|
313
|
+
{{ game.i18n.localize(props.label) }}
|
|
314
|
+
</span>
|
|
315
|
+
</template>
|
|
316
|
+
<template #append-inner>
|
|
317
|
+
<i-calculator
|
|
318
|
+
:context="props.context"
|
|
319
|
+
:systemPath="props.systemPath"
|
|
320
|
+
:primaryColor="props.primaryColor"
|
|
321
|
+
:secondaryColor="props.secondaryColor">
|
|
322
|
+
</i-calculator>
|
|
323
|
+
</template>
|
|
324
|
+
</v-number-input>
|
|
325
|
+
|
|
326
|
+
<!-- Single Currency Money (Display Mode) -->
|
|
327
|
+
<v-text-field
|
|
328
|
+
v-else-if="!hasDenominations && !props.editMode"
|
|
329
|
+
:model-value="formattedSingleDisplay"
|
|
330
|
+
readonly
|
|
331
|
+
:color="fieldColor"
|
|
332
|
+
density="compact"
|
|
333
|
+
variant="outlined"
|
|
334
|
+
:data-tooltip="exactAmountTooltip"
|
|
335
|
+
>
|
|
336
|
+
<template #label>
|
|
337
|
+
<v-tooltip :text="exactAmountTooltip">
|
|
338
|
+
<template v-slot:activator="{ props: tooltipProps }">
|
|
339
|
+
<span class="field-label" v-bind="tooltipProps">
|
|
340
|
+
<v-icon v-if="props.icon" :icon="props.icon" size="small" class="me-1"></v-icon>
|
|
341
|
+
{{ game.i18n.localize(props.label) }}
|
|
342
|
+
</span>
|
|
343
|
+
</template>
|
|
344
|
+
</v-tooltip>
|
|
345
|
+
</template>
|
|
346
|
+
</v-text-field>
|
|
347
|
+
|
|
348
|
+
<!-- Multi-Denomination Money -->
|
|
349
|
+
<v-input v-else class="isdl-money-denominations">
|
|
350
|
+
<template #default>
|
|
351
|
+
<v-field
|
|
352
|
+
class="v-field--active"
|
|
353
|
+
density="compact"
|
|
354
|
+
variant="outlined"
|
|
355
|
+
>
|
|
356
|
+
<template #label>
|
|
357
|
+
<span class="field-label">
|
|
358
|
+
<v-icon v-if="props.icon" :icon="props.icon" size="small" class="me-1"></v-icon>
|
|
359
|
+
{{ game.i18n.localize(props.label) }}
|
|
360
|
+
</span>
|
|
361
|
+
</template>
|
|
362
|
+
<template #append-inner>
|
|
363
|
+
<v-icon
|
|
364
|
+
:icon="showDenominationPanel ? 'fa-solid fa-caret-up' : 'fa-solid fa-caret-down'"
|
|
365
|
+
@click.stop="showDenominationPanel = !showDenominationPanel"
|
|
366
|
+
class="v-select__menu-icon"
|
|
367
|
+
/>
|
|
368
|
+
</template>
|
|
369
|
+
<div class="money-content flexcol">
|
|
370
|
+
<div class="d-flex money-inner-content">
|
|
371
|
+
<span v-html="formattedDenominationDisplay" />
|
|
372
|
+
</div>
|
|
373
|
+
<v-expand-transition>
|
|
374
|
+
<div v-show="showDenominationPanel" class="money-expanded-content" style="margin-top: 1rem;">
|
|
375
|
+
<div v-for="denom in denominations" :key="denom.name" class="denomination-row">
|
|
376
|
+
<v-number-input
|
|
377
|
+
:model-value="value[denom.name.toLowerCase()] || 0"
|
|
378
|
+
@update:model-value="(newVal) => onDenominationChange(denom.name.toLowerCase(), newVal)"
|
|
379
|
+
:name="\`\${props.systemPath}.\${denom.name.toLowerCase()}\`"
|
|
380
|
+
:disabled="isDisabled"
|
|
381
|
+
:color="denom.color || fieldColor"
|
|
382
|
+
:controlVariant="isDisabled ? 'hidden' : 'stacked'"
|
|
383
|
+
density="compact"
|
|
384
|
+
variant="outlined"
|
|
385
|
+
hide-details
|
|
386
|
+
class="mb-2"
|
|
387
|
+
>
|
|
388
|
+
<template #label>
|
|
389
|
+
<span class="field-label">
|
|
390
|
+
<v-icon v-if="denom.icon" :icon="denom.icon" :color="denom.color" size="small" class="me-1"></v-icon>
|
|
391
|
+
{{ denom.name }}
|
|
392
|
+
</span>
|
|
393
|
+
</template>
|
|
394
|
+
<template #append-inner>
|
|
395
|
+
<i-calculator
|
|
396
|
+
v-if="props.editMode && !isDisabled"
|
|
397
|
+
:context="props.context"
|
|
398
|
+
:systemPath="\`\${props.systemPath}.\${denom.name.toLowerCase()}\`"
|
|
399
|
+
:primaryColor="props.primaryColor"
|
|
400
|
+
:secondaryColor="props.secondaryColor">
|
|
401
|
+
</i-calculator>
|
|
402
|
+
<v-btn
|
|
403
|
+
v-if="!isDisabled"
|
|
404
|
+
icon="fa-solid fa-right-left"
|
|
405
|
+
size="x-small"
|
|
406
|
+
variant="text"
|
|
407
|
+
@click.stop="openConversionDialog(denom)"
|
|
408
|
+
style="opacity: 0.7;"
|
|
409
|
+
>
|
|
410
|
+
</v-btn>
|
|
411
|
+
</template>
|
|
412
|
+
</v-number-input>
|
|
413
|
+
</div>
|
|
414
|
+
</div>
|
|
415
|
+
</v-expand-transition>
|
|
416
|
+
</div>
|
|
417
|
+
</v-field>
|
|
418
|
+
</template>
|
|
419
|
+
</v-input>
|
|
420
|
+
|
|
421
|
+
<!-- Conversion Dialog -->
|
|
422
|
+
<v-dialog v-model="showConversionDialog" max-width="500">
|
|
423
|
+
<v-card>
|
|
424
|
+
<v-card-title>
|
|
425
|
+
<span class="text-h6">Convert {{ conversionSource?.name }}</span>
|
|
426
|
+
</v-card-title>
|
|
427
|
+
<v-card-text>
|
|
428
|
+
<div class="d-flex flex-column gap-3">
|
|
429
|
+
<v-number-input
|
|
430
|
+
v-model="conversionAmount"
|
|
431
|
+
label="Amount to convert"
|
|
432
|
+
:hint="\`Available: \${conversionPreview.sourceValue}\`"
|
|
433
|
+
persistent-hint
|
|
434
|
+
density="compact"
|
|
435
|
+
variant="outlined"
|
|
436
|
+
controlVariant="stacked"
|
|
437
|
+
:min="0"
|
|
438
|
+
:max="conversionPreview.sourceValue"
|
|
439
|
+
/>
|
|
440
|
+
|
|
441
|
+
<v-select
|
|
442
|
+
v-model="conversionTarget"
|
|
443
|
+
:items="denominations.filter(d => d.name !== conversionSource?.name)"
|
|
444
|
+
item-title="name"
|
|
445
|
+
label="Convert to"
|
|
446
|
+
return-object
|
|
447
|
+
density="compact"
|
|
448
|
+
variant="outlined"
|
|
449
|
+
>
|
|
450
|
+
<template v-slot:item="{ item, props: itemProps }">
|
|
451
|
+
<v-list-item v-bind="itemProps">
|
|
452
|
+
<template v-slot:prepend>
|
|
453
|
+
<v-icon v-if="item.raw.icon" :icon="item.raw.icon" :color="item.raw.color"></v-icon>
|
|
454
|
+
</template>
|
|
455
|
+
</v-list-item>
|
|
456
|
+
</template>
|
|
457
|
+
</v-select>
|
|
458
|
+
|
|
459
|
+
<v-alert v-if="conversionPreview.insufficient" type="error" density="compact">
|
|
460
|
+
Insufficient funds
|
|
461
|
+
</v-alert>
|
|
462
|
+
|
|
463
|
+
<v-alert v-else-if="conversionPreview.valid" type="info" density="compact">
|
|
464
|
+
<div class="text-body-2">
|
|
465
|
+
<strong>Preview:</strong><br/>
|
|
466
|
+
{{ conversionSource?.name }}: {{ conversionPreview.sourceValue }} → {{ conversionPreview.sourceValue - conversionAmount }}<br/>
|
|
467
|
+
{{ conversionTarget?.name }}: {{ conversionPreview.targetValue }} → {{ conversionPreview.targetValue + conversionPreview.result }}
|
|
468
|
+
</div>
|
|
469
|
+
</v-alert>
|
|
470
|
+
</div>
|
|
471
|
+
</v-card-text>
|
|
472
|
+
<v-card-actions>
|
|
473
|
+
<v-spacer></v-spacer>
|
|
474
|
+
<v-btn
|
|
475
|
+
variant="text"
|
|
476
|
+
@click="showConversionDialog = false"
|
|
477
|
+
>
|
|
478
|
+
Cancel
|
|
479
|
+
</v-btn>
|
|
480
|
+
<v-btn
|
|
481
|
+
:color="props.primaryColor || 'primary'"
|
|
482
|
+
variant="elevated"
|
|
483
|
+
@click="executeConversion"
|
|
484
|
+
:disabled="!conversionPreview.valid"
|
|
485
|
+
>
|
|
486
|
+
Convert
|
|
487
|
+
</v-btn>
|
|
488
|
+
</v-card-actions>
|
|
489
|
+
</v-card>
|
|
490
|
+
</v-dialog>
|
|
491
|
+
</div>
|
|
492
|
+
</template>
|
|
493
|
+
`.appendNewLine();
|
|
494
|
+
fs.writeFileSync(generatedFilePath, toString(fileNode));
|
|
495
|
+
}
|
|
496
|
+
//# sourceMappingURL=vue-money.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vue-money.js","sourceRoot":"","sources":["../../../../../src/cli/components/vue/base-components/vue-money.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,EAAC,YAAY,EAAE,QAAQ,EAAC,MAAM,kBAAkB,CAAC;AAGxD,MAAM,CAAC,OAAO,UAAU,sBAAsB,CAAC,WAAmB,EAAE,KAAa;IAC7E,MAAM,gBAAgB,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,EAAE,WAAW,EAAE,KAAK,EAAE,YAAY,CAAC,CAAC;IAC5F,MAAM,iBAAiB,GAAG,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,WAAW,CAAC,CAAC;IAEnE,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,gBAAgB,CAAC,EAAE;QAClC,EAAE,CAAC,SAAS,CAAC,gBAAgB,EAAE,EAAC,SAAS,EAAE,IAAI,EAAC,CAAC,CAAC;KACrD;IAED,MAAM,QAAQ,GAAG,YAAY,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAme5B,CAAC,aAAa,EAAE,CAAC;IAElB,EAAE,CAAC,aAAa,CAAC,iBAAiB,EAAE,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC;AAC5D,CAAC"}
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import * as path from 'node:path';
|
|
2
|
+
import * as fs from 'node:fs';
|
|
3
|
+
import { expandToNode, toString } from 'langium/generate';
|
|
4
|
+
export default function generateNumberComponent(destination, entry) {
|
|
5
|
+
const generatedFileDir = path.join(destination, "system", "templates", "vue", "components");
|
|
6
|
+
const generatedFilePath = path.join(generatedFileDir, `number.vue`);
|
|
7
|
+
if (!fs.existsSync(generatedFileDir)) {
|
|
8
|
+
fs.mkdirSync(generatedFileDir, { recursive: true });
|
|
9
|
+
}
|
|
10
|
+
const fileNode = expandToNode `
|
|
11
|
+
<script setup>
|
|
12
|
+
import { ref, computed, inject } from "vue";
|
|
13
|
+
|
|
14
|
+
const props = defineProps({
|
|
15
|
+
label: String,
|
|
16
|
+
systemPath: String,
|
|
17
|
+
context: Object,
|
|
18
|
+
visibility: String,
|
|
19
|
+
editMode: Boolean,
|
|
20
|
+
icon: String,
|
|
21
|
+
color: String,
|
|
22
|
+
disabled: Boolean,
|
|
23
|
+
hasValueParam: Boolean,
|
|
24
|
+
primaryColor: String,
|
|
25
|
+
secondaryColor: String,
|
|
26
|
+
max: Number,
|
|
27
|
+
calculator: {
|
|
28
|
+
type: Boolean,
|
|
29
|
+
default: undefined
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
const document = inject("rawDocument");
|
|
34
|
+
|
|
35
|
+
const numberInput = ref(null);
|
|
36
|
+
|
|
37
|
+
const value = computed({
|
|
38
|
+
get: () => foundry.utils.getProperty(props.context, props.systemPath),
|
|
39
|
+
set: (newValue) => foundry.utils.setProperty(props.context, props.systemPath, newValue)
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
// Vuetify's up/down stepper buttons update the model without firing a
|
|
43
|
+
// native change event, so Foundry's submitOnChange form handler never
|
|
44
|
+
// persists the new value. When a change arrives while the text input is
|
|
45
|
+
// NOT focused (i.e. it came from a stepper click, not typing), persist
|
|
46
|
+
// directly via document.update — the same reliable path the dice fields
|
|
47
|
+
// use (dispatching a synthetic change risks Foundry reading the DOM
|
|
48
|
+
// input before Vue has flushed the new value). Typing still persists via
|
|
49
|
+
// the input's own native change on blur/enter.
|
|
50
|
+
// Note: 'document' is the injected Foundry document; DOM access must go
|
|
51
|
+
// through window.document.
|
|
52
|
+
const onValueUpdate = (newValue) => {
|
|
53
|
+
value.value = newValue;
|
|
54
|
+
const input = numberInput.value?.\$el?.querySelector('input');
|
|
55
|
+
if (document && input && window.document.activeElement !== input) {
|
|
56
|
+
document.update({ [props.systemPath]: newValue });
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
const isHidden = computed(() => {
|
|
61
|
+
if (props.visibility === "hidden") {
|
|
62
|
+
return true;
|
|
63
|
+
}
|
|
64
|
+
if (props.visibility === "gm" && !game.user.isGM) {
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
return false;
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
const isDisabled = computed(() => {
|
|
71
|
+
return props.disabled ||
|
|
72
|
+
props.visibility === "locked" ||
|
|
73
|
+
props.visibility === "readonly" ||
|
|
74
|
+
(props.visibility === "gmOnly" && !game.user.isGM);
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
const fieldColor = computed(() => {
|
|
78
|
+
return props.color || 'primary';
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
const isCalculated = computed(() => {
|
|
82
|
+
return props.hasValueParam;
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
const controlVariant = computed(() => {
|
|
86
|
+
return isCalculated.value ? 'hidden' : 'stacked';
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
const classes = computed(() => {
|
|
90
|
+
return isCalculated.value ? 'calculated-number' : '';
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
const showCalculator = computed(() => {
|
|
94
|
+
// Check if calculator was explicitly passed as a prop
|
|
95
|
+
const hasCalculatorProp = props.calculator !== undefined && props.calculator !== false;
|
|
96
|
+
const calculatorExplicitlyFalse = props.calculator === false;
|
|
97
|
+
|
|
98
|
+
// If calculator param is explicitly set to true, use it
|
|
99
|
+
if (hasCalculatorProp) {
|
|
100
|
+
return true;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// If calculator param is explicitly set to false, never show
|
|
104
|
+
if (calculatorExplicitlyFalse) {
|
|
105
|
+
return false;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Don't show on calculated fields
|
|
109
|
+
if (isCalculated.value) {
|
|
110
|
+
return false;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Show if max > 10
|
|
114
|
+
if (props.max && props.max > 10) {
|
|
115
|
+
return true;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// When max is undefined, show if current value >= 10 or <= -10
|
|
119
|
+
if (props.max === undefined) {
|
|
120
|
+
const currentValue = value.value;
|
|
121
|
+
if (typeof currentValue === 'number' && (currentValue >= 10 || currentValue <= -10)) {
|
|
122
|
+
return true;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return false;
|
|
127
|
+
});
|
|
128
|
+
</script>
|
|
129
|
+
|
|
130
|
+
<template>
|
|
131
|
+
<div v-if="!isHidden" class="isdl-number single-wide">
|
|
132
|
+
<v-number-input
|
|
133
|
+
v-if="!isCalculated"
|
|
134
|
+
ref="numberInput"
|
|
135
|
+
:model-value="value"
|
|
136
|
+
@update:model-value="onValueUpdate"
|
|
137
|
+
:name="props.systemPath"
|
|
138
|
+
:disabled="isDisabled"
|
|
139
|
+
:color="fieldColor"
|
|
140
|
+
controlVariant="stacked"
|
|
141
|
+
density="compact"
|
|
142
|
+
variant="outlined"
|
|
143
|
+
>
|
|
144
|
+
<template #label>
|
|
145
|
+
<span class="field-label">
|
|
146
|
+
<v-icon v-if="props.icon" :icon="props.icon" size="small" class="me-1"></v-icon>
|
|
147
|
+
{{ game.i18n.localize(props.label) }}
|
|
148
|
+
</span>
|
|
149
|
+
</template>
|
|
150
|
+
<template #append-inner v-if="props.editMode && showCalculator">
|
|
151
|
+
<i-calculator
|
|
152
|
+
:context="props.context"
|
|
153
|
+
:systemPath="props.systemPath"
|
|
154
|
+
:primaryColor="props.primaryColor"
|
|
155
|
+
:secondaryColor="props.secondaryColor">
|
|
156
|
+
</i-calculator>
|
|
157
|
+
</template>
|
|
158
|
+
</v-number-input>
|
|
159
|
+
|
|
160
|
+
<v-number-input
|
|
161
|
+
v-else
|
|
162
|
+
:model-value="value"
|
|
163
|
+
:name="props.systemPath"
|
|
164
|
+
:disabled="isDisabled"
|
|
165
|
+
:color="fieldColor"
|
|
166
|
+
controlVariant="hidden"
|
|
167
|
+
density="compact"
|
|
168
|
+
variant="outlined"
|
|
169
|
+
append-inner-icon="fa-solid fa-function"
|
|
170
|
+
class="calculated-number single-wide"
|
|
171
|
+
>
|
|
172
|
+
<template #label>
|
|
173
|
+
<span class="field-label">
|
|
174
|
+
<v-icon v-if="props.icon" :icon="props.icon" size="small" class="me-1"></v-icon>
|
|
175
|
+
{{ game.i18n.localize(props.label) }}
|
|
176
|
+
</span>
|
|
177
|
+
</template>
|
|
178
|
+
</v-number-input>
|
|
179
|
+
</div>
|
|
180
|
+
</template>
|
|
181
|
+
`.appendNewLine();
|
|
182
|
+
fs.writeFileSync(generatedFilePath, toString(fileNode));
|
|
183
|
+
}
|
|
184
|
+
//# sourceMappingURL=vue-number.js.map
|