@shwfed/config 2.12.11 → 2.12.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/dist/module.json +1 -1
- package/dist/runtime/components/config/blocks/2026-05-06/com.shwfed.block.table/config.d.vue.ts +68 -68
- package/dist/runtime/components/config/blocks/2026-05-06/com.shwfed.block.table/config.vue.d.ts +68 -68
- package/dist/runtime/components/config/blocks/2026-05-06/com.shwfed.block.table/runtime.d.vue.ts +68 -68
- package/dist/runtime/components/config/blocks/2026-05-06/com.shwfed.block.table/runtime.vue.d.ts +68 -68
- package/dist/runtime/components/config/blocks/2026-05-06/com.shwfed.block.table/schema.d.ts +34 -34
- package/dist/runtime/components/form/fields/2026-04-28/com.shwfed.form.field.number/runtime.vue +22 -15
- package/dist/runtime/components/form/fields/2026-04-28/com.shwfed.form.field.numberrange/runtime.vue +34 -13
- package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.multi/runtime.vue +22 -18
- package/dist/runtime/components/form/utils/derived.js +2 -2
- package/dist/runtime/components/form/utils/state.d.ts +18 -0
- package/dist/runtime/components/form/utils/state.js +15 -2
- package/dist/runtime/components/table/columns/2026-05-20/com.shwfed.table.column.number-input/runtime.vue +22 -14
- package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-multi/config.d.vue.ts +2 -2
- package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-multi/config.vue.d.ts +2 -2
- package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-single/config.d.vue.ts +2 -2
- package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-single/config.vue.d.ts +2 -2
- package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-multi/config.d.vue.ts +2 -2
- package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-multi/config.vue.d.ts +2 -2
- package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-single/config.d.vue.ts +2 -2
- package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-single/config.vue.d.ts +2 -2
- package/dist/runtime/components/table/columns/2026-06-14/com.shwfed.table.column.tree-combobox-multi/config.d.vue.ts +2 -2
- package/dist/runtime/components/table/columns/2026-06-14/com.shwfed.table.column.tree-combobox-multi/config.vue.d.ts +2 -2
- package/dist/runtime/components/table/columns/2026-06-14/com.shwfed.table.column.tree-combobox-single/config.d.vue.ts +2 -2
- package/dist/runtime/components/table/columns/2026-06-14/com.shwfed.table.column.tree-combobox-single/config.vue.d.ts +2 -2
- package/dist/runtime/components/table/config.vue +1 -4
- package/dist/runtime/components/table/index.vue +2 -2
- package/dist/runtime/components/table/schema.d.ts +68 -68
- package/dist/runtime/share/number-format.d.ts +1 -0
- package/dist/runtime/share/number-format.js +12 -13
- package/package.json +1 -1
|
@@ -47,40 +47,6 @@ export declare function schema(configure: (env: Environment) => void, _blockRef:
|
|
|
47
47
|
readonly message: string;
|
|
48
48
|
}[]] | undefined;
|
|
49
49
|
}[];
|
|
50
|
-
readonly query?: {
|
|
51
|
-
readonly style?: string | undefined;
|
|
52
|
-
readonly id?: string | undefined;
|
|
53
|
-
readonly initial?: {
|
|
54
|
-
readonly data: string;
|
|
55
|
-
readonly request?: string | undefined;
|
|
56
|
-
} | undefined;
|
|
57
|
-
readonly displayName?: string | undefined;
|
|
58
|
-
readonly kind: "shwfed.component.form";
|
|
59
|
-
readonly fields: readonly any[];
|
|
60
|
-
readonly layouts: readonly {
|
|
61
|
-
readonly name: string;
|
|
62
|
-
readonly layout: {
|
|
63
|
-
readonly style?: string | undefined;
|
|
64
|
-
readonly columns: number;
|
|
65
|
-
readonly gap?: number | undefined;
|
|
66
|
-
readonly rows?: number | undefined;
|
|
67
|
-
readonly placements: {
|
|
68
|
-
readonly [x: string]: {
|
|
69
|
-
readonly area: readonly [readonly [number, number], readonly [number, number]];
|
|
70
|
-
readonly v?: "stretch" | "center" | "end" | "start" | undefined;
|
|
71
|
-
readonly h?: "stretch" | "center" | "end" | "start" | undefined;
|
|
72
|
-
};
|
|
73
|
-
};
|
|
74
|
-
};
|
|
75
|
-
readonly media?: string | undefined;
|
|
76
|
-
}[];
|
|
77
|
-
readonly readonly?: string | undefined;
|
|
78
|
-
} | undefined;
|
|
79
|
-
readonly dataSource?: {
|
|
80
|
-
readonly data: string;
|
|
81
|
-
readonly total?: string | undefined;
|
|
82
|
-
readonly request?: string | undefined;
|
|
83
|
-
} | undefined;
|
|
84
50
|
readonly actions?: {
|
|
85
51
|
readonly size: "default" | "sm" | "xs";
|
|
86
52
|
readonly style?: string | undefined;
|
|
@@ -148,6 +114,40 @@ export declare function schema(configure: (env: Environment) => void, _blockRef:
|
|
|
148
114
|
readonly variant?: "default" | "link" | "destructive" | "primary" | "ghost" | undefined;
|
|
149
115
|
}[];
|
|
150
116
|
} | undefined;
|
|
117
|
+
readonly query?: {
|
|
118
|
+
readonly style?: string | undefined;
|
|
119
|
+
readonly id?: string | undefined;
|
|
120
|
+
readonly initial?: {
|
|
121
|
+
readonly data: string;
|
|
122
|
+
readonly request?: string | undefined;
|
|
123
|
+
} | undefined;
|
|
124
|
+
readonly displayName?: string | undefined;
|
|
125
|
+
readonly kind: "shwfed.component.form";
|
|
126
|
+
readonly fields: readonly any[];
|
|
127
|
+
readonly layouts: readonly {
|
|
128
|
+
readonly name: string;
|
|
129
|
+
readonly layout: {
|
|
130
|
+
readonly style?: string | undefined;
|
|
131
|
+
readonly columns: number;
|
|
132
|
+
readonly gap?: number | undefined;
|
|
133
|
+
readonly rows?: number | undefined;
|
|
134
|
+
readonly placements: {
|
|
135
|
+
readonly [x: string]: {
|
|
136
|
+
readonly area: readonly [readonly [number, number], readonly [number, number]];
|
|
137
|
+
readonly v?: "stretch" | "center" | "end" | "start" | undefined;
|
|
138
|
+
readonly h?: "stretch" | "center" | "end" | "start" | undefined;
|
|
139
|
+
};
|
|
140
|
+
};
|
|
141
|
+
};
|
|
142
|
+
readonly media?: string | undefined;
|
|
143
|
+
}[];
|
|
144
|
+
readonly readonly?: string | undefined;
|
|
145
|
+
} | undefined;
|
|
146
|
+
readonly dataSource?: {
|
|
147
|
+
readonly data: string;
|
|
148
|
+
readonly total?: string | undefined;
|
|
149
|
+
readonly request?: string | undefined;
|
|
150
|
+
} | undefined;
|
|
151
151
|
readonly bottomActions?: {
|
|
152
152
|
readonly size: "default" | "sm" | "xs";
|
|
153
153
|
readonly style?: string | undefined;
|
package/dist/runtime/components/form/fields/2026-04-28/com.shwfed.form.field.number/runtime.vue
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
<script setup>
|
|
2
2
|
import { Icon } from "@iconify/vue";
|
|
3
3
|
import { Effect } from "effect";
|
|
4
|
-
import { computed, nextTick } from "vue";
|
|
4
|
+
import { computed, nextTick, watch } from "vue";
|
|
5
5
|
import { useI18n } from "vue-i18n";
|
|
6
6
|
import { cel as _rawCel } from "../../../../../utils/cel";
|
|
7
7
|
import { celBindings, injectCELContext } from "../../../../../utils/cel-context";
|
|
8
8
|
import { getLocalizedText } from "../../../../../share/locale";
|
|
9
9
|
import { interpolateMarkdown } from "../../../../table/utils/runtime";
|
|
10
|
-
import { formatNumberDisplay } from "../../../../../share/number-format";
|
|
10
|
+
import { formatNumberDisplay, roundToPrecision } from "../../../../../share/number-format";
|
|
11
11
|
import { Field, FieldLabel, FieldMessages } from "../../../../ui/field";
|
|
12
12
|
import { InputGroup, InputGroupAddon, InputGroupButton, InputGroupNumberField } from "../../../../ui/input-group";
|
|
13
13
|
import { Markdown } from "../../../../ui/markdown";
|
|
@@ -16,7 +16,7 @@ import { DEFAULT_FIELD_ORIENTATION } from "../../../utils/common";
|
|
|
16
16
|
import { useFieldValue } from "../../../utils/field-value";
|
|
17
17
|
import { useFieldValidation } from "../../../utils/validation";
|
|
18
18
|
import { useFormReadonly } from "../../../utils/readonly";
|
|
19
|
-
import { useFormScope } from "../../../utils/state";
|
|
19
|
+
import { useFormScope, useFormState } from "../../../utils/state";
|
|
20
20
|
defineOptions({ name: "ShwfedNumberFieldRuntime" });
|
|
21
21
|
const props = defineProps({
|
|
22
22
|
fieldId: { type: String, required: true },
|
|
@@ -86,22 +86,29 @@ const { draft, commit } = useFieldValue({
|
|
|
86
86
|
return props.config.valueAsString ? String(next) : next;
|
|
87
87
|
}
|
|
88
88
|
});
|
|
89
|
+
const bag = useFormState();
|
|
90
|
+
watch(
|
|
91
|
+
() => [props.config.binding, props.config.precision, props.config.roundingMode, props.config.valueAsString],
|
|
92
|
+
([binding, precision, roundingMode, valueAsString], _prev, onCleanup) => {
|
|
93
|
+
if (binding == null || precision === void 0) return;
|
|
94
|
+
const mode = roundingMode ?? "round";
|
|
95
|
+
const unregister = bag.registerCoercion(binding, (value) => {
|
|
96
|
+
let n;
|
|
97
|
+
if (typeof value === "number" && Number.isFinite(value)) n = value;
|
|
98
|
+
else if (typeof value === "string" && value.length > 0 && Number.isFinite(Number(value))) n = Number(value);
|
|
99
|
+
if (n === void 0) return value;
|
|
100
|
+
const rounded = roundToPrecision(n, precision, mode);
|
|
101
|
+
return valueAsString ? String(rounded) : rounded;
|
|
102
|
+
});
|
|
103
|
+
onCleanup(unregister);
|
|
104
|
+
},
|
|
105
|
+
{ immediate: true }
|
|
106
|
+
);
|
|
89
107
|
const readonlyDisplay = computed(() => formatNumberDisplay(draft.value, {
|
|
90
108
|
displayMode: props.config.displayMode,
|
|
91
109
|
precision: props.config.precision,
|
|
92
110
|
roundingMode: props.config.roundingMode
|
|
93
111
|
}));
|
|
94
|
-
function applyRounding(n, precision, mode) {
|
|
95
|
-
const factor = 10 ** precision;
|
|
96
|
-
switch (mode) {
|
|
97
|
-
case "floor":
|
|
98
|
-
return Math.floor(n * factor) / factor;
|
|
99
|
-
case "ceil":
|
|
100
|
-
return Math.ceil(n * factor) / factor;
|
|
101
|
-
default:
|
|
102
|
-
return Math.round(n * factor) / factor;
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
112
|
const addonConfig = computed(() => {
|
|
106
113
|
const addon = props.config.addon;
|
|
107
114
|
if (!addon || addon.items.length === 0) return null;
|
|
@@ -125,7 +132,7 @@ async function onBlur() {
|
|
|
125
132
|
if (precision !== void 0) {
|
|
126
133
|
const current = draft.value;
|
|
127
134
|
if (current !== void 0) {
|
|
128
|
-
const rounded =
|
|
135
|
+
const rounded = roundToPrecision(current, precision, props.config.roundingMode ?? "round");
|
|
129
136
|
if (rounded !== current) draft.value = rounded;
|
|
130
137
|
}
|
|
131
138
|
}
|
package/dist/runtime/components/form/fields/2026-04-28/com.shwfed.form.field.numberrange/runtime.vue
CHANGED
|
@@ -6,6 +6,7 @@ import { useI18n } from "vue-i18n";
|
|
|
6
6
|
import { cel as _rawCel } from "../../../../../utils/cel";
|
|
7
7
|
import { celBindings, injectCELContext } from "../../../../../utils/cel-context";
|
|
8
8
|
import { getLocalizedText } from "../../../../../share/locale";
|
|
9
|
+
import { roundToPrecision } from "../../../../../share/number-format";
|
|
9
10
|
import { interpolateMarkdown } from "../../../../table/utils/runtime";
|
|
10
11
|
import { Field, FieldLabel, FieldMessages } from "../../../../ui/field";
|
|
11
12
|
import { InputGroup, InputGroupAddon, InputGroupButton, InputGroupNumberField } from "../../../../ui/input-group";
|
|
@@ -21,7 +22,8 @@ const props = defineProps({
|
|
|
21
22
|
config: { type: null, required: true }
|
|
22
23
|
});
|
|
23
24
|
const { locale } = useI18n();
|
|
24
|
-
const
|
|
25
|
+
const bag = useFormState();
|
|
26
|
+
const { getAt, setAt } = bag;
|
|
25
27
|
const formScope = useFormScope();
|
|
26
28
|
const inherited = injectCELContext();
|
|
27
29
|
const $cel = (expression, context) => _rawCel(expression, { ...celBindings(inherited), ...context });
|
|
@@ -158,17 +160,6 @@ const endMin = computed(() => {
|
|
|
158
160
|
if (typeof s === "number") return s;
|
|
159
161
|
return m;
|
|
160
162
|
});
|
|
161
|
-
function applyRounding(n, precision, mode) {
|
|
162
|
-
const factor = 10 ** precision;
|
|
163
|
-
switch (mode) {
|
|
164
|
-
case "floor":
|
|
165
|
-
return Math.floor(n * factor) / factor;
|
|
166
|
-
case "ceil":
|
|
167
|
-
return Math.ceil(n * factor) / factor;
|
|
168
|
-
default:
|
|
169
|
-
return Math.round(n * factor) / factor;
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
163
|
async function onBlurSide(side) {
|
|
173
164
|
await nextTick();
|
|
174
165
|
const precision = props.config.precision;
|
|
@@ -176,12 +167,42 @@ async function onBlurSide(side) {
|
|
|
176
167
|
const ref_ = side === "start" ? localStart : localEnd;
|
|
177
168
|
const current = ref_.value;
|
|
178
169
|
if (current !== void 0) {
|
|
179
|
-
const rounded =
|
|
170
|
+
const rounded = roundToPrecision(current, precision, props.config.roundingMode ?? "round");
|
|
180
171
|
if (rounded !== current) ref_.value = rounded;
|
|
181
172
|
}
|
|
182
173
|
}
|
|
183
174
|
commit();
|
|
184
175
|
}
|
|
176
|
+
function roundScalar(precision, mode, value) {
|
|
177
|
+
let n;
|
|
178
|
+
if (typeof value === "number" && Number.isFinite(value)) n = value;
|
|
179
|
+
else if (typeof value === "string" && value.length > 0 && Number.isFinite(Number(value))) n = Number(value);
|
|
180
|
+
if (n === void 0) return value;
|
|
181
|
+
const rounded = roundToPrecision(n, precision, mode);
|
|
182
|
+
return props.config.valueAsString ? String(rounded) : rounded;
|
|
183
|
+
}
|
|
184
|
+
watch(
|
|
185
|
+
() => [props.config.binding, props.config.precision, props.config.roundingMode, props.config.valueAsString],
|
|
186
|
+
([binding, precision, roundingMode], _prev, onCleanup) => {
|
|
187
|
+
if (binding == null || precision === void 0) return;
|
|
188
|
+
const mode = roundingMode ?? "round";
|
|
189
|
+
const unregisters = [];
|
|
190
|
+
if (typeof binding === "string") {
|
|
191
|
+
unregisters.push(bag.registerCoercion(
|
|
192
|
+
binding,
|
|
193
|
+
(value) => Array.isArray(value) && value.length === 2 ? [roundScalar(precision, mode, value[0]), roundScalar(precision, mode, value[1])] : value
|
|
194
|
+
));
|
|
195
|
+
} else {
|
|
196
|
+
for (const path of binding) {
|
|
197
|
+
unregisters.push(bag.registerCoercion(path, (value) => roundScalar(precision, mode, value)));
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
onCleanup(() => {
|
|
201
|
+
for (const off of unregisters) off();
|
|
202
|
+
});
|
|
203
|
+
},
|
|
204
|
+
{ immediate: true }
|
|
205
|
+
);
|
|
185
206
|
const showClear = computed(
|
|
186
207
|
() => !isDisabled.value && (localStart.value !== void 0 || localEnd.value !== void 0)
|
|
187
208
|
);
|
package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.multi/runtime.vue
CHANGED
|
@@ -397,29 +397,33 @@ const readonlyText = computed(() => {
|
|
|
397
397
|
:class="isDisabled ? 'pointer-events-none opacity-60' : void 0"
|
|
398
398
|
>
|
|
399
399
|
<template #node="{ node, selected, indeterminate }">
|
|
400
|
-
<span class="flex
|
|
401
|
-
<!--
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
<
|
|
406
|
-
:
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
400
|
+
<span class="flex flex-col gap-0.5">
|
|
401
|
+
<!-- Checkbox shares a centered row with the label so it aligns to
|
|
402
|
+
the label's line box (not the top of the label+tooltip stack).
|
|
403
|
+
The tooltip drops below, indented `pl-6` (checkbox `size-4` +
|
|
404
|
+
`gap-2`) to hang under the label text. -->
|
|
405
|
+
<span class="flex items-center gap-2">
|
|
406
|
+
<!-- Presentational checkbox: mirrors the row's selection state but
|
|
407
|
+
never owns it. `pointer-events-none` + `tabindex=-1` keep the
|
|
408
|
+
existing row-click / keyboard toggle in `<UiTree>` the single
|
|
409
|
+
source of truth — the control is a visual reflection only. -->
|
|
410
|
+
<Checkbox
|
|
411
|
+
:model-value="indeterminate ? 'indeterminate' : selected"
|
|
412
|
+
class="pointer-events-none shrink-0"
|
|
413
|
+
tabindex="-1"
|
|
414
|
+
aria-hidden="true"
|
|
415
|
+
/>
|
|
412
416
|
<Markdown
|
|
413
417
|
:source="nodeLabelText(node)"
|
|
414
418
|
class="prose prose-sm prose-zinc text-zinc-700"
|
|
415
419
|
/>
|
|
416
|
-
<Markdown
|
|
417
|
-
v-if="nodeTooltipText(node)"
|
|
418
|
-
:source="nodeTooltipText(node)"
|
|
419
|
-
block
|
|
420
|
-
class="prose prose-xs prose-zinc text-zinc-400"
|
|
421
|
-
/>
|
|
422
420
|
</span>
|
|
421
|
+
<Markdown
|
|
422
|
+
v-if="nodeTooltipText(node)"
|
|
423
|
+
:source="nodeTooltipText(node)"
|
|
424
|
+
block
|
|
425
|
+
class="prose prose-xs prose-zinc text-zinc-400 pl-6"
|
|
426
|
+
/>
|
|
423
427
|
</span>
|
|
424
428
|
</template>
|
|
425
429
|
|
|
@@ -55,7 +55,7 @@ export function useDerivedQuiescence() {
|
|
|
55
55
|
return inject(QUIESCENCE_KEY, null) ?? createQuiescence();
|
|
56
56
|
}
|
|
57
57
|
export function useDerived(options) {
|
|
58
|
-
const { state, getAt, setAtSilent, isDirty, markDirty } = options.formState;
|
|
58
|
+
const { state, getAt, setAtSilent, isDirty, markDirty, coerce } = options.formState;
|
|
59
59
|
const quiescence = options.quiescence;
|
|
60
60
|
const derivedFields = computed(
|
|
61
61
|
() => options.fields().flatMap((field) => {
|
|
@@ -76,7 +76,7 @@ export function useDerived(options) {
|
|
|
76
76
|
(result) => {
|
|
77
77
|
if (gen !== generation) return;
|
|
78
78
|
if (field.mode === "prefill" && isDirty(field.binding)) return;
|
|
79
|
-
const normalized = result === void 0 ? null : result;
|
|
79
|
+
const normalized = coerce(field.binding, result === void 0 ? null : result);
|
|
80
80
|
if (!deepEqual(getAt(field.binding), normalized)) setAtSilent(field.binding, normalized);
|
|
81
81
|
},
|
|
82
82
|
() => {
|
|
@@ -63,6 +63,24 @@ export type FormStateBag = {
|
|
|
63
63
|
* expression will not overwrite it.
|
|
64
64
|
*/
|
|
65
65
|
markDirty: (path: string) => void;
|
|
66
|
+
/**
|
|
67
|
+
* Register a value coercion for one binding. It runs on EVERY write to that
|
|
68
|
+
* path — user commit, `setAtSilent`, `state.write` action, or a `derived`
|
|
69
|
+
* write-back — so a field whose stored shape is constrained can enforce that
|
|
70
|
+
* constraint at the storage boundary rather than only in its own input
|
|
71
|
+
* handler. The number field registers rounding-to-小数位数 here, so a value a
|
|
72
|
+
* `derived` formula computes (which never passes through the field's blur
|
|
73
|
+
* handler) still lands rounded. Returns an unregister.
|
|
74
|
+
*
|
|
75
|
+
* The coercion MUST be idempotent — `coerce(coerce(x))` has to equal
|
|
76
|
+
* `coerce(x)`. `useDerived` compares its freshly evaluated result against the
|
|
77
|
+
* already-coerced stored value to decide whether to re-write; a non-idempotent
|
|
78
|
+
* coercion would make that comparison never converge and loop the formula on
|
|
79
|
+
* its own write-back.
|
|
80
|
+
*/
|
|
81
|
+
registerCoercion: (path: string, fn: (value: unknown) => unknown) => () => void;
|
|
82
|
+
/** Apply the coercion registered for `path` (identity when none). */
|
|
83
|
+
coerce: (path: string, value: unknown) => unknown;
|
|
66
84
|
};
|
|
67
85
|
export declare const FORM_STATE_KEY: InjectionKey<FormStateBag>;
|
|
68
86
|
export declare function provideFormState(state: Ref<unknown>, kind?: FormStateBagKind): FormStateBag;
|
|
@@ -5,8 +5,14 @@ export const FORM_STATE_KEY = Symbol("shwfed-form-state");
|
|
|
5
5
|
export function provideFormState(state, kind = "form") {
|
|
6
6
|
const parent = inject(FORM_STATE_KEY, void 0);
|
|
7
7
|
const dirty = ref(/* @__PURE__ */ new Set());
|
|
8
|
+
const coercions = /* @__PURE__ */ new Map();
|
|
9
|
+
function coerce(path, value) {
|
|
10
|
+
const fn = coercions.get(path);
|
|
11
|
+
return fn ? fn(value) : value;
|
|
12
|
+
}
|
|
8
13
|
function write(path, value) {
|
|
9
|
-
const
|
|
14
|
+
const coerced = coerce(path, value === void 0 ? null : value);
|
|
15
|
+
const normalized = coerced === void 0 ? null : coerced;
|
|
10
16
|
if (path === SELF_BINDING) {
|
|
11
17
|
state.value = normalized;
|
|
12
18
|
return;
|
|
@@ -30,7 +36,14 @@ export function provideFormState(state, kind = "form") {
|
|
|
30
36
|
setAtSilent: write,
|
|
31
37
|
dirty,
|
|
32
38
|
isDirty: (path) => dirty.value.has(path),
|
|
33
|
-
markDirty
|
|
39
|
+
markDirty,
|
|
40
|
+
registerCoercion: (path, fn) => {
|
|
41
|
+
coercions.set(path, fn);
|
|
42
|
+
return () => {
|
|
43
|
+
if (coercions.get(path) === fn) coercions.delete(path);
|
|
44
|
+
};
|
|
45
|
+
},
|
|
46
|
+
coerce
|
|
34
47
|
};
|
|
35
48
|
provide(FORM_STATE_KEY, bag);
|
|
36
49
|
return bag;
|
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
<script setup>
|
|
2
2
|
import { Icon } from "@iconify/vue";
|
|
3
3
|
import { Effect } from "effect";
|
|
4
|
-
import { computed, nextTick } from "vue";
|
|
4
|
+
import { computed, nextTick, watch } from "vue";
|
|
5
5
|
import { useI18n } from "vue-i18n";
|
|
6
6
|
import { cel as _rawCel } from "../../../../../utils/cel";
|
|
7
7
|
import { celScope, injectCELContext } from "../../../../../utils/cel-context";
|
|
8
8
|
import { useFormReadonly } from "../../../../form/utils/readonly";
|
|
9
9
|
import { getLocalizedText } from "../../../../../share/locale";
|
|
10
|
-
import { formatNumberDisplay } from "../../../../../share/number-format";
|
|
10
|
+
import { formatNumberDisplay, roundToPrecision } from "../../../../../share/number-format";
|
|
11
11
|
import { InputGroup, InputGroupAddon, InputGroupButton, InputGroupNumberField } from "../../../../ui/input-group";
|
|
12
12
|
import ShwfedActions from "../../../../actions/components/group.vue";
|
|
13
13
|
import { useFieldValue } from "../../../../form/utils/field-value";
|
|
14
|
+
import { useFormState } from "../../../../form/utils/state";
|
|
14
15
|
import { JUSTIFY_CLASS, TEXT_ALIGN_CLASS } from "../../../utils/runtime";
|
|
15
16
|
defineOptions({ name: "ShwfedTableNumberInputRendererRuntime" });
|
|
16
17
|
const props = defineProps({
|
|
@@ -76,17 +77,24 @@ const readonlyDisplay = computed(() => formatNumberDisplay(draft.value, {
|
|
|
76
77
|
precision: props.column.precision,
|
|
77
78
|
roundingMode: props.column.roundingMode
|
|
78
79
|
}));
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
80
|
+
const bag = useFormState();
|
|
81
|
+
watch(
|
|
82
|
+
() => [props.column.binding, props.column.precision, props.column.roundingMode, props.column.valueAsString],
|
|
83
|
+
([binding, precision, roundingMode, valueAsString], _prev, onCleanup) => {
|
|
84
|
+
if (binding == null || precision === void 0) return;
|
|
85
|
+
const mode = roundingMode ?? "round";
|
|
86
|
+
const unregister = bag.registerCoercion(binding, (value) => {
|
|
87
|
+
let n;
|
|
88
|
+
if (typeof value === "number" && Number.isFinite(value)) n = value;
|
|
89
|
+
else if (typeof value === "string" && value.length > 0 && Number.isFinite(Number(value))) n = Number(value);
|
|
90
|
+
if (n === void 0) return value;
|
|
91
|
+
const rounded = roundToPrecision(n, precision, mode);
|
|
92
|
+
return valueAsString ? String(rounded) : rounded;
|
|
93
|
+
});
|
|
94
|
+
onCleanup(unregister);
|
|
95
|
+
},
|
|
96
|
+
{ immediate: true }
|
|
97
|
+
);
|
|
90
98
|
const addonConfig = computed(() => {
|
|
91
99
|
const addon = props.column.addon;
|
|
92
100
|
if (!addon || addon.items.length === 0) return null;
|
|
@@ -112,7 +120,7 @@ async function onBlur() {
|
|
|
112
120
|
if (precision !== void 0) {
|
|
113
121
|
const current = draft.value;
|
|
114
122
|
if (current !== void 0) {
|
|
115
|
-
const rounded =
|
|
123
|
+
const rounded = roundToPrecision(current, precision, props.column.roundingMode ?? "round");
|
|
116
124
|
if (rounded !== current) draft.value = rounded;
|
|
117
125
|
}
|
|
118
126
|
}
|
|
@@ -43,6 +43,7 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
|
|
|
43
43
|
readonly data: string;
|
|
44
44
|
readonly request?: string | undefined;
|
|
45
45
|
};
|
|
46
|
+
readonly enableSorting?: boolean | undefined;
|
|
46
47
|
readonly nodeKey: string;
|
|
47
48
|
readonly nodeChildren: string;
|
|
48
49
|
readonly nodeLabel: readonly [{
|
|
@@ -52,7 +53,6 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
|
|
|
52
53
|
readonly locale: "en" | "ja" | "ko";
|
|
53
54
|
readonly message: string;
|
|
54
55
|
}[]];
|
|
55
|
-
readonly enableSorting?: boolean | undefined;
|
|
56
56
|
readonly cascade: "independent" | "cascade-down" | "cascade-both";
|
|
57
57
|
readonly nodeTooltip?: readonly [{
|
|
58
58
|
readonly locale: "zh";
|
|
@@ -106,6 +106,7 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
|
|
|
106
106
|
readonly data: string;
|
|
107
107
|
readonly request?: string | undefined;
|
|
108
108
|
};
|
|
109
|
+
readonly enableSorting?: boolean | undefined;
|
|
109
110
|
readonly nodeKey: string;
|
|
110
111
|
readonly nodeChildren: string;
|
|
111
112
|
readonly nodeLabel: readonly [{
|
|
@@ -115,7 +116,6 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
|
|
|
115
116
|
readonly locale: "en" | "ja" | "ko";
|
|
116
117
|
readonly message: string;
|
|
117
118
|
}[]];
|
|
118
|
-
readonly enableSorting?: boolean | undefined;
|
|
119
119
|
readonly cascade: "independent" | "cascade-down" | "cascade-both";
|
|
120
120
|
readonly nodeTooltip?: readonly [{
|
|
121
121
|
readonly locale: "zh";
|
|
@@ -43,6 +43,7 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
|
|
|
43
43
|
readonly data: string;
|
|
44
44
|
readonly request?: string | undefined;
|
|
45
45
|
};
|
|
46
|
+
readonly enableSorting?: boolean | undefined;
|
|
46
47
|
readonly nodeKey: string;
|
|
47
48
|
readonly nodeChildren: string;
|
|
48
49
|
readonly nodeLabel: readonly [{
|
|
@@ -52,7 +53,6 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
|
|
|
52
53
|
readonly locale: "en" | "ja" | "ko";
|
|
53
54
|
readonly message: string;
|
|
54
55
|
}[]];
|
|
55
|
-
readonly enableSorting?: boolean | undefined;
|
|
56
56
|
readonly cascade: "independent" | "cascade-down" | "cascade-both";
|
|
57
57
|
readonly nodeTooltip?: readonly [{
|
|
58
58
|
readonly locale: "zh";
|
|
@@ -106,6 +106,7 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
|
|
|
106
106
|
readonly data: string;
|
|
107
107
|
readonly request?: string | undefined;
|
|
108
108
|
};
|
|
109
|
+
readonly enableSorting?: boolean | undefined;
|
|
109
110
|
readonly nodeKey: string;
|
|
110
111
|
readonly nodeChildren: string;
|
|
111
112
|
readonly nodeLabel: readonly [{
|
|
@@ -115,7 +116,6 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
|
|
|
115
116
|
readonly locale: "en" | "ja" | "ko";
|
|
116
117
|
readonly message: string;
|
|
117
118
|
}[]];
|
|
118
|
-
readonly enableSorting?: boolean | undefined;
|
|
119
119
|
readonly cascade: "independent" | "cascade-down" | "cascade-both";
|
|
120
120
|
readonly nodeTooltip?: readonly [{
|
|
121
121
|
readonly locale: "zh";
|
|
@@ -43,6 +43,7 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
|
|
|
43
43
|
readonly data: string;
|
|
44
44
|
readonly request?: string | undefined;
|
|
45
45
|
};
|
|
46
|
+
readonly enableSorting?: boolean | undefined;
|
|
46
47
|
readonly nodeKey: string;
|
|
47
48
|
readonly nodeChildren: string;
|
|
48
49
|
readonly nodeLabel: readonly [{
|
|
@@ -52,7 +53,6 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
|
|
|
52
53
|
readonly locale: "en" | "ja" | "ko";
|
|
53
54
|
readonly message: string;
|
|
54
55
|
}[]];
|
|
55
|
-
readonly enableSorting?: boolean | undefined;
|
|
56
56
|
readonly nodeTooltip?: readonly [{
|
|
57
57
|
readonly locale: "zh";
|
|
58
58
|
readonly message: string;
|
|
@@ -105,6 +105,7 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
|
|
|
105
105
|
readonly data: string;
|
|
106
106
|
readonly request?: string | undefined;
|
|
107
107
|
};
|
|
108
|
+
readonly enableSorting?: boolean | undefined;
|
|
108
109
|
readonly nodeKey: string;
|
|
109
110
|
readonly nodeChildren: string;
|
|
110
111
|
readonly nodeLabel: readonly [{
|
|
@@ -114,7 +115,6 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
|
|
|
114
115
|
readonly locale: "en" | "ja" | "ko";
|
|
115
116
|
readonly message: string;
|
|
116
117
|
}[]];
|
|
117
|
-
readonly enableSorting?: boolean | undefined;
|
|
118
118
|
readonly nodeTooltip?: readonly [{
|
|
119
119
|
readonly locale: "zh";
|
|
120
120
|
readonly message: string;
|
|
@@ -43,6 +43,7 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
|
|
|
43
43
|
readonly data: string;
|
|
44
44
|
readonly request?: string | undefined;
|
|
45
45
|
};
|
|
46
|
+
readonly enableSorting?: boolean | undefined;
|
|
46
47
|
readonly nodeKey: string;
|
|
47
48
|
readonly nodeChildren: string;
|
|
48
49
|
readonly nodeLabel: readonly [{
|
|
@@ -52,7 +53,6 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
|
|
|
52
53
|
readonly locale: "en" | "ja" | "ko";
|
|
53
54
|
readonly message: string;
|
|
54
55
|
}[]];
|
|
55
|
-
readonly enableSorting?: boolean | undefined;
|
|
56
56
|
readonly nodeTooltip?: readonly [{
|
|
57
57
|
readonly locale: "zh";
|
|
58
58
|
readonly message: string;
|
|
@@ -105,6 +105,7 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
|
|
|
105
105
|
readonly data: string;
|
|
106
106
|
readonly request?: string | undefined;
|
|
107
107
|
};
|
|
108
|
+
readonly enableSorting?: boolean | undefined;
|
|
108
109
|
readonly nodeKey: string;
|
|
109
110
|
readonly nodeChildren: string;
|
|
110
111
|
readonly nodeLabel: readonly [{
|
|
@@ -114,7 +115,6 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
|
|
|
114
115
|
readonly locale: "en" | "ja" | "ko";
|
|
115
116
|
readonly message: string;
|
|
116
117
|
}[]];
|
|
117
|
-
readonly enableSorting?: boolean | undefined;
|
|
118
118
|
readonly nodeTooltip?: readonly [{
|
|
119
119
|
readonly locale: "zh";
|
|
120
120
|
readonly message: string;
|
|
@@ -44,6 +44,7 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
|
|
|
44
44
|
readonly data: string;
|
|
45
45
|
readonly request?: string | undefined;
|
|
46
46
|
};
|
|
47
|
+
readonly enableSorting?: boolean | undefined;
|
|
47
48
|
readonly nodeKey: string;
|
|
48
49
|
readonly nodeChildren: string;
|
|
49
50
|
readonly nodeLabel: readonly [{
|
|
@@ -53,7 +54,6 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
|
|
|
53
54
|
readonly locale: "en" | "ja" | "ko";
|
|
54
55
|
readonly message: string;
|
|
55
56
|
}[]];
|
|
56
|
-
readonly enableSorting?: boolean | undefined;
|
|
57
57
|
readonly cascade: "independent" | "cascade-down" | "cascade-both";
|
|
58
58
|
readonly nodeTooltip?: readonly [{
|
|
59
59
|
readonly locale: "zh";
|
|
@@ -108,6 +108,7 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
|
|
|
108
108
|
readonly data: string;
|
|
109
109
|
readonly request?: string | undefined;
|
|
110
110
|
};
|
|
111
|
+
readonly enableSorting?: boolean | undefined;
|
|
111
112
|
readonly nodeKey: string;
|
|
112
113
|
readonly nodeChildren: string;
|
|
113
114
|
readonly nodeLabel: readonly [{
|
|
@@ -117,7 +118,6 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
|
|
|
117
118
|
readonly locale: "en" | "ja" | "ko";
|
|
118
119
|
readonly message: string;
|
|
119
120
|
}[]];
|
|
120
|
-
readonly enableSorting?: boolean | undefined;
|
|
121
121
|
readonly cascade: "independent" | "cascade-down" | "cascade-both";
|
|
122
122
|
readonly nodeTooltip?: readonly [{
|
|
123
123
|
readonly locale: "zh";
|
|
@@ -44,6 +44,7 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
|
|
|
44
44
|
readonly data: string;
|
|
45
45
|
readonly request?: string | undefined;
|
|
46
46
|
};
|
|
47
|
+
readonly enableSorting?: boolean | undefined;
|
|
47
48
|
readonly nodeKey: string;
|
|
48
49
|
readonly nodeChildren: string;
|
|
49
50
|
readonly nodeLabel: readonly [{
|
|
@@ -53,7 +54,6 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
|
|
|
53
54
|
readonly locale: "en" | "ja" | "ko";
|
|
54
55
|
readonly message: string;
|
|
55
56
|
}[]];
|
|
56
|
-
readonly enableSorting?: boolean | undefined;
|
|
57
57
|
readonly cascade: "independent" | "cascade-down" | "cascade-both";
|
|
58
58
|
readonly nodeTooltip?: readonly [{
|
|
59
59
|
readonly locale: "zh";
|
|
@@ -108,6 +108,7 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
|
|
|
108
108
|
readonly data: string;
|
|
109
109
|
readonly request?: string | undefined;
|
|
110
110
|
};
|
|
111
|
+
readonly enableSorting?: boolean | undefined;
|
|
111
112
|
readonly nodeKey: string;
|
|
112
113
|
readonly nodeChildren: string;
|
|
113
114
|
readonly nodeLabel: readonly [{
|
|
@@ -117,7 +118,6 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
|
|
|
117
118
|
readonly locale: "en" | "ja" | "ko";
|
|
118
119
|
readonly message: string;
|
|
119
120
|
}[]];
|
|
120
|
-
readonly enableSorting?: boolean | undefined;
|
|
121
121
|
readonly cascade: "independent" | "cascade-down" | "cascade-both";
|
|
122
122
|
readonly nodeTooltip?: readonly [{
|
|
123
123
|
readonly locale: "zh";
|
|
@@ -44,6 +44,7 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
|
|
|
44
44
|
readonly data: string;
|
|
45
45
|
readonly request?: string | undefined;
|
|
46
46
|
};
|
|
47
|
+
readonly enableSorting?: boolean | undefined;
|
|
47
48
|
readonly nodeKey: string;
|
|
48
49
|
readonly nodeChildren: string;
|
|
49
50
|
readonly nodeLabel: readonly [{
|
|
@@ -53,7 +54,6 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
|
|
|
53
54
|
readonly locale: "en" | "ja" | "ko";
|
|
54
55
|
readonly message: string;
|
|
55
56
|
}[]];
|
|
56
|
-
readonly enableSorting?: boolean | undefined;
|
|
57
57
|
readonly nodeTooltip?: readonly [{
|
|
58
58
|
readonly locale: "zh";
|
|
59
59
|
readonly message: string;
|
|
@@ -107,6 +107,7 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
|
|
|
107
107
|
readonly data: string;
|
|
108
108
|
readonly request?: string | undefined;
|
|
109
109
|
};
|
|
110
|
+
readonly enableSorting?: boolean | undefined;
|
|
110
111
|
readonly nodeKey: string;
|
|
111
112
|
readonly nodeChildren: string;
|
|
112
113
|
readonly nodeLabel: readonly [{
|
|
@@ -116,7 +117,6 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
|
|
|
116
117
|
readonly locale: "en" | "ja" | "ko";
|
|
117
118
|
readonly message: string;
|
|
118
119
|
}[]];
|
|
119
|
-
readonly enableSorting?: boolean | undefined;
|
|
120
120
|
readonly nodeTooltip?: readonly [{
|
|
121
121
|
readonly locale: "zh";
|
|
122
122
|
readonly message: string;
|