@effect-app/vue-components 4.0.0-beta.314 → 4.0.0-beta.316
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/types/components/Dialog.vue.d.ts +1 -1
- package/dist/types/components/OmegaForm/InputProps.d.ts +1 -0
- package/dist/types/components/OmegaForm/OmegaInputVuetify.vue.d.ts +6 -0
- package/dist/types/components/OmegaForm/OmegaInternalInput.vue.d.ts +1 -0
- package/dist/types/components/OmegaForm/decimalSeparatorInput.d.ts +13 -0
- package/dist/vue-components.es.js +9 -9
- package/dist/vue-components21.es.js +14 -4
- package/dist/vue-components32.es.js +14 -23
- package/dist/vue-components33.es.js +23 -299
- package/dist/vue-components34.es.js +344 -0
- package/dist/vue-components36.es.js +7 -72
- package/dist/vue-components37.es.js +72 -3
- package/dist/vue-components38.es.js +4 -63
- package/dist/vue-components39.es.js +63 -4
- package/dist/vue-components40.es.js +4 -23
- package/dist/vue-components41.es.js +23 -4
- package/dist/vue-components42.es.js +3 -57
- package/dist/vue-components43.es.js +57 -3
- package/dist/vue-components44.es.js +4 -11
- package/dist/vue-components45.es.js +11 -21
- package/dist/vue-components46.es.js +22 -0
- package/dist/vue-components48.es.js +8 -3
- package/dist/vue-components49.es.js +3 -37
- package/dist/vue-components50.es.js +34 -23
- package/dist/vue-components51.es.js +23 -24
- package/dist/vue-components52.es.js +27 -6
- package/dist/vue-components53.es.js +6 -17
- package/dist/vue-components54.es.js +16 -34
- package/dist/vue-components55.es.js +34 -16
- package/dist/vue-components56.es.js +16 -19
- package/dist/vue-components57.es.js +10 -19
- package/dist/vue-components58.es.js +29 -6
- package/dist/vue-components59.es.js +6 -8
- package/dist/vue-components60.es.js +7 -36
- package/dist/vue-components61.es.js +37 -24
- package/dist/vue-components62.es.js +19 -122
- package/dist/vue-components63.es.js +126 -22
- package/dist/vue-components64.es.js +20 -17
- package/dist/vue-components65.es.js +18 -6
- package/dist/vue-components66.es.js +5 -15
- package/dist/vue-components67.es.js +18 -4
- package/dist/vue-components68.es.js +4 -28
- package/dist/vue-components69.es.js +28 -4
- package/dist/vue-components70.es.js +4 -42
- package/dist/vue-components71.es.js +38 -96
- package/dist/vue-components72.es.js +95 -30
- package/dist/vue-components73.es.js +35 -18
- package/dist/vue-components74.es.js +18 -49
- package/dist/vue-components75.es.js +50 -0
- package/package.json +3 -3
- package/src/components/OmegaForm/InputProps.ts +1 -0
- package/src/components/OmegaForm/OmegaInputVuetify.vue +65 -9
- package/src/components/OmegaForm/OmegaInternalInput.vue +1 -0
- package/src/components/OmegaForm/decimalSeparatorInput.ts +38 -0
- package/src/components/OmegaForm/validation/localized.ts +15 -4
- package/dist/vue-components35.es.js +0 -8
- package/dist/vue-components47.es.js +0 -9
|
@@ -87,20 +87,54 @@
|
|
|
87
87
|
/>
|
|
88
88
|
</template>
|
|
89
89
|
</v-textarea>
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
90
|
+
<!-- min/max are deliberately NOT passed as VNumberInput props: the component
|
|
91
|
+
silently withholds out-of-range values from the model (so schema errors
|
|
92
|
+
would never show) and clamps on blur. Validation stays schema-driven; the
|
|
93
|
+
bounds are exposed to AT via the spinbutton ARIA attrs, which fall through
|
|
94
|
+
to the native input. Same reasoning for precision: Vuetify's default (0)
|
|
95
|
+
would silently block decimals, so it's forced to null and typing 1.5 into
|
|
96
|
+
an int field shows the schema error instead. -->
|
|
97
|
+
<v-number-input
|
|
98
|
+
v-if="inputProps.type === 'number'"
|
|
93
99
|
:id="inputProps.id"
|
|
94
100
|
:required="inputProps.required"
|
|
95
|
-
|
|
96
|
-
:
|
|
97
|
-
:
|
|
101
|
+
role="spinbutton"
|
|
102
|
+
:aria-valuemin="typeof inputProps.min === 'number' ? inputProps.min : undefined"
|
|
103
|
+
:aria-valuemax="typeof inputProps.max === 'number' ? inputProps.max : undefined"
|
|
104
|
+
:aria-valuenow="typeof state.value === 'number' ? state.value : undefined"
|
|
98
105
|
:name="field.name"
|
|
99
106
|
:label="inputProps.label"
|
|
100
107
|
:error-messages="inputProps.errorMessages"
|
|
101
108
|
:error="inputProps.error"
|
|
109
|
+
:precision="null"
|
|
110
|
+
control-variant="stacked"
|
|
102
111
|
v-bind="$attrs"
|
|
103
|
-
:model-value="state.value"
|
|
112
|
+
:model-value="state.value as any"
|
|
113
|
+
@beforeinput.capture="onNumberBeforeinput"
|
|
114
|
+
@update:model-value="(v: number | null) => field.handleChange((v ?? undefined) as any)"
|
|
115
|
+
>
|
|
116
|
+
<template
|
|
117
|
+
v-if="$slots.label"
|
|
118
|
+
#label
|
|
119
|
+
>
|
|
120
|
+
<slot
|
|
121
|
+
name="label"
|
|
122
|
+
v-bind="{ required: inputProps.required, id: inputProps.id, label: inputProps.label }"
|
|
123
|
+
/>
|
|
124
|
+
</template>
|
|
125
|
+
</v-number-input>
|
|
126
|
+
<v-slider
|
|
127
|
+
v-if="inputProps.type === 'range'"
|
|
128
|
+
:id="inputProps.id"
|
|
129
|
+
:required="inputProps.required"
|
|
130
|
+
:min="typeof inputProps.min === 'number' ? inputProps.min : undefined"
|
|
131
|
+
:max="typeof inputProps.max === 'number' ? inputProps.max : undefined"
|
|
132
|
+
:name="field.name"
|
|
133
|
+
:label="inputProps.label"
|
|
134
|
+
:error-messages="inputProps.errorMessages"
|
|
135
|
+
:error="inputProps.error"
|
|
136
|
+
v-bind="$attrs"
|
|
137
|
+
:model-value="state.value as any"
|
|
104
138
|
@update:model-value="(e: any) => {
|
|
105
139
|
if (e || e === 0) {
|
|
106
140
|
field.handleChange(Number(e) as any)
|
|
@@ -118,7 +152,7 @@
|
|
|
118
152
|
v-bind="{ required: inputProps.required, id: inputProps.id, label: inputProps.label }"
|
|
119
153
|
/>
|
|
120
154
|
</template>
|
|
121
|
-
</
|
|
155
|
+
</v-slider>
|
|
122
156
|
<template v-if="inputProps.type === 'radio'">
|
|
123
157
|
<v-radio-group
|
|
124
158
|
:id="inputProps.id"
|
|
@@ -239,7 +273,9 @@
|
|
|
239
273
|
generic="From extends Record<PropertyKey, any>, Name extends DeepKeys<From>"
|
|
240
274
|
>
|
|
241
275
|
import { type DeepKeys } from "@tanstack/vue-form"
|
|
242
|
-
import { computed, watchEffect } from "vue"
|
|
276
|
+
import { computed, useAttrs, watchEffect } from "vue"
|
|
277
|
+
import { useLocale } from "vuetify"
|
|
278
|
+
import { handleDecimalSeparatorBeforeinput } from "./decimalSeparatorInput"
|
|
243
279
|
import type { VuetifyInputProps } from "./InputProps"
|
|
244
280
|
import { getInputType } from "./inputs"
|
|
245
281
|
import { typeOverrides } from "./types"
|
|
@@ -255,6 +291,26 @@ defineOptions({
|
|
|
255
291
|
inheritAttrs: false
|
|
256
292
|
})
|
|
257
293
|
|
|
294
|
+
const attrs = useAttrs()
|
|
295
|
+
// useLocale throws outside a Vuetify app (e.g. tests mounting with stubbed
|
|
296
|
+
// vuetify components); numbers then fall back to the "." separator.
|
|
297
|
+
const localeDecimalSeparator = (() => {
|
|
298
|
+
try {
|
|
299
|
+
return useLocale().decimalSeparator
|
|
300
|
+
} catch {
|
|
301
|
+
return undefined
|
|
302
|
+
}
|
|
303
|
+
})()
|
|
304
|
+
|
|
305
|
+
// Mirrors VNumberInput's own resolution: an explicit decimal-separator attr
|
|
306
|
+
// wins, otherwise the locale decides.
|
|
307
|
+
const decimalSeparator = computed(() => {
|
|
308
|
+
const explicit = (attrs["decimal-separator"] ?? attrs["decimalSeparator"]) as string | undefined
|
|
309
|
+
return explicit?.[0] || localeDecimalSeparator?.value || "."
|
|
310
|
+
})
|
|
311
|
+
|
|
312
|
+
const onNumberBeforeinput = (e: Event) => handleDecimalSeparatorBeforeinput(e as InputEvent, decimalSeparator.value)
|
|
313
|
+
|
|
258
314
|
// True when no dedicated branch handles `inputProps.type` (it's outside the
|
|
259
315
|
// built-in `typeOverrides`): the fallback text input renders and we warn.
|
|
260
316
|
const isUnhandledType = computed(() => !(typeOverrides as readonly string[]).includes(props.inputProps.type))
|
|
@@ -191,6 +191,7 @@ const inputProps: ComputedRef<InputProps<From, Name>> = computed(() => ({
|
|
|
191
191
|
? (props.meta?.minimum
|
|
192
192
|
?? (typeof props.meta?.exclusiveMinimum === "number" ? props.meta.exclusiveMinimum + 1 : undefined))
|
|
193
193
|
: undefined,
|
|
194
|
+
refinement: props.meta?.type === "number" ? props.meta?.refinement : undefined,
|
|
194
195
|
errorMessages: errors.value,
|
|
195
196
|
error: !!errors.value.length,
|
|
196
197
|
type: fieldType.value,
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
const escapeForRegex = (s: string) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* VNumberInput only accepts the active decimal separator and silently drops
|
|
5
|
+
* the other one while typing. Attached in capture phase on the component
|
|
6
|
+
* root, this handler lets users type either "." or ",": the wrong character
|
|
7
|
+
* is translated to the active separator before Vuetify's own beforeinput
|
|
8
|
+
* filter can reject it.
|
|
9
|
+
*
|
|
10
|
+
* No validation beyond Vuetify's own single-separator typing rule: OmegaForm
|
|
11
|
+
* deliberately lets out-of-schema values through so schema errors show,
|
|
12
|
+
* instead of silently blocking input (same reasoning as min/max not being
|
|
13
|
+
* passed as props).
|
|
14
|
+
*/
|
|
15
|
+
export const handleDecimalSeparatorBeforeinput = (e: InputEvent, separator: string) => {
|
|
16
|
+
if (!e.data) return
|
|
17
|
+
// The active separator may be any single char (locale or explicit prop,
|
|
18
|
+
// e.g. "٫"); everything from [".", ","] that isn't it gets translated.
|
|
19
|
+
const wrongs = [".", ","].filter((c) => c !== separator)
|
|
20
|
+
if (!wrongs.some((c) => e.data!.includes(c))) return
|
|
21
|
+
|
|
22
|
+
const input = e.target as HTMLInputElement
|
|
23
|
+
e.preventDefault()
|
|
24
|
+
e.stopPropagation()
|
|
25
|
+
|
|
26
|
+
const data = wrongs.reduce((acc, c) => acc.replaceAll(c, separator), e.data)
|
|
27
|
+
const start = input.selectionStart ?? input.value.length
|
|
28
|
+
const end = input.selectionEnd ?? input.value.length
|
|
29
|
+
const next = input.value.slice(0, start) + data + input.value.slice(end)
|
|
30
|
+
// Mirrors Vuetify's own typing filter: at most one separator, "-" only at
|
|
31
|
+
// the start. A second separator would only produce an unparseable string.
|
|
32
|
+
if (!new RegExp(`^-?\\d*${escapeForRegex(separator)}?\\d*$`).test(next)) return
|
|
33
|
+
|
|
34
|
+
input.value = next
|
|
35
|
+
const cursor = start + data.length
|
|
36
|
+
input.setSelectionRange(cursor, cursor)
|
|
37
|
+
input.dispatchEvent(new Event("input", { bubbles: true }))
|
|
38
|
+
}
|
|
@@ -13,6 +13,7 @@ type FilterMeta =
|
|
|
13
13
|
| { readonly _tag: "isGreaterThan"; readonly exclusiveMinimum: number }
|
|
14
14
|
| { readonly _tag: "isLessThanOrEqualTo"; readonly maximum: number }
|
|
15
15
|
| { readonly _tag: "isLessThan"; readonly exclusiveMaximum: number }
|
|
16
|
+
| { readonly _tag: "isBetween"; readonly minimum: number; readonly maximum: number }
|
|
16
17
|
| { readonly _tag?: undefined }
|
|
17
18
|
|
|
18
19
|
/** Map filter annotations (representation since beta.107, legacy meta before) to FilterMeta. */
|
|
@@ -85,20 +86,30 @@ export const makeStandardSchemaV1Hooks = (
|
|
|
85
86
|
const actual = input !== undefined ? String(input) : "NaN"
|
|
86
87
|
return trans("validation.integer.expected", { actualValue: actual })
|
|
87
88
|
}
|
|
89
|
+
// isExclusive semantics in the message catalog: true = strict bound
|
|
90
|
+
// ("greater/less than"), false = inclusive bound ("at least/at most").
|
|
88
91
|
case "isGreaterThanOrEqualTo":
|
|
89
92
|
return trans(
|
|
90
93
|
meta.minimum === 0 ? "validation.number.positive" : "validation.number.min",
|
|
91
|
-
{ minimum: meta.minimum, isExclusive:
|
|
94
|
+
{ minimum: meta.minimum, isExclusive: false }
|
|
92
95
|
)
|
|
93
96
|
case "isGreaterThan":
|
|
94
97
|
return trans(
|
|
95
98
|
meta.exclusiveMinimum === 0 ? "validation.number.positive" : "validation.number.min",
|
|
96
|
-
{ minimum: meta.exclusiveMinimum, isExclusive:
|
|
99
|
+
{ minimum: meta.exclusiveMinimum, isExclusive: true }
|
|
97
100
|
)
|
|
98
101
|
case "isLessThanOrEqualTo":
|
|
99
|
-
return trans("validation.number.max", { maximum: meta.maximum, isExclusive:
|
|
102
|
+
return trans("validation.number.max", { maximum: meta.maximum, isExclusive: false })
|
|
100
103
|
case "isLessThan":
|
|
101
|
-
return trans("validation.number.max", { maximum: meta.exclusiveMaximum, isExclusive:
|
|
104
|
+
return trans("validation.number.max", { maximum: meta.exclusiveMaximum, isExclusive: true })
|
|
105
|
+
case "isBetween": {
|
|
106
|
+
// Inclusive on both ends; report the side the value actually violated.
|
|
107
|
+
const input = reportedInput(issue)
|
|
108
|
+
const below = typeof input === "number" && input < meta.minimum
|
|
109
|
+
return below
|
|
110
|
+
? trans("validation.number.min", { minimum: meta.minimum, isExclusive: false })
|
|
111
|
+
: trans("validation.number.max", { maximum: meta.maximum, isExclusive: false })
|
|
112
|
+
}
|
|
102
113
|
default:
|
|
103
114
|
// Fall back to the default check hook so custom S.makeFilter messages
|
|
104
115
|
// (which surface as InvalidValue.annotations.message on issue.issue)
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
(function(){try{if(typeof document<`u`){var e=document.createElement(`style`);if(e.appendChild(document.createTextNode(`.omega-input .v-input__details:has(.v-messages:empty){grid-template-rows:0fr;transition:all .2s}.omega-input .v-messages:empty{min-height:0}.omega-input .v-input__details:has(.v-messages){grid-template-rows:1fr;min-height:0;transition:all .2s;display:grid;overflow:hidden}.omega-input .v-messages{transition:all .2s}.omega-input .v-messages>*{transition-duration:0s!important}.omega-input [role=alert]:has(.v-messages:empty){padding:0}.omega-input .v-btn{cursor:pointer;appearance:none;width:auto;box-shadow:none;min-width:auto;height:auto;padding:.5em .5em .5em 1em;display:block}`)),document.head.appendChild(e),window.customElements){let e=window.customElements.define;window.customElements.define=function(t,n){let r=n.prototype.connectedCallback;return n.prototype.connectedCallback=function(){if(r&&r.call(this),this.shadowRoot){let e=document.createElement(`style`);e.appendChild(document.createTextNode(`.omega-input .v-input__details:has(.v-messages:empty){grid-template-rows:0fr;transition:all .2s}.omega-input .v-messages:empty{min-height:0}.omega-input .v-input__details:has(.v-messages){grid-template-rows:1fr;min-height:0;transition:all .2s;display:grid;overflow:hidden}.omega-input .v-messages{transition:all .2s}.omega-input .v-messages>*{transition-duration:0s!important}.omega-input [role=alert]:has(.v-messages:empty){padding:0}.omega-input .v-btn{cursor:pointer;appearance:none;width:auto;box-shadow:none;min-width:auto;height:auto;padding:.5em .5em .5em 1em;display:block}`)),this.shadowRoot.appendChild(e)}},e.call(window.customElements,t,n)}}}}catch(e){console.error(`vite-plugin-css-injected-by-js`,e)}})();
|
|
2
|
-
(function(){try{if(typeof document<`u`){var e=document.createElement(`style`);if(e.appendChild(document.createTextNode(`.omega-input .v-input__details:has(.v-messages:empty){grid-template-rows:0fr;transition:all .2s}.omega-input .v-messages:empty{min-height:0}.omega-input .v-input__details:has(.v-messages){grid-template-rows:1fr;min-height:0;transition:all .2s;display:grid;overflow:hidden}.omega-input .v-messages{transition:all .2s}.omega-input .v-messages>*{transition-duration:0s!important}.omega-input [role=alert]:has(.v-messages:empty){padding:0}.omega-input .v-btn{cursor:pointer;appearance:none;width:auto;box-shadow:none;min-width:auto;height:auto;padding:.5em .5em .5em 1em;display:block}`)),document.head.appendChild(e),window.customElements){let e=window.customElements.define;window.customElements.define=function(t,n){let r=n.prototype.connectedCallback;return n.prototype.connectedCallback=function(){if(r&&r.call(this),this.shadowRoot){let e=document.createElement(`style`);e.appendChild(document.createTextNode(`.omega-input .v-input__details:has(.v-messages:empty){grid-template-rows:0fr;transition:all .2s}.omega-input .v-messages:empty{min-height:0}.omega-input .v-input__details:has(.v-messages){grid-template-rows:1fr;min-height:0;transition:all .2s;display:grid;overflow:hidden}.omega-input .v-messages{transition:all .2s}.omega-input .v-messages>*{transition-duration:0s!important}.omega-input [role=alert]:has(.v-messages:empty){padding:0}.omega-input .v-btn{cursor:pointer;appearance:none;width:auto;box-shadow:none;min-width:auto;height:auto;padding:.5em .5em .5em 1em;display:block}`)),this.shadowRoot.appendChild(e)}},e.call(window.customElements,t,n)}}}}catch(e){console.error(`vite-plugin-css-injected-by-js`,e)}})();
|
|
3
|
-
import e from "./vue-components33.es.js";
|
|
4
|
-
|
|
5
|
-
//#region src/components/OmegaForm/OmegaInputVuetify.vue
|
|
6
|
-
var t = e;
|
|
7
|
-
//#endregion
|
|
8
|
-
export { t as default };
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
(function(){try{if(typeof document<`u`){var e=document.createElement(`style`);if(e.appendChild(document.createTextNode(`fieldset[data-v-13a7a1b6]{display:contents}fieldset[disabled][data-v-13a7a1b6]>*{pointer-events:none}`)),document.head.appendChild(e),window.customElements){let e=window.customElements.define;window.customElements.define=function(t,n){let r=n.prototype.connectedCallback;return n.prototype.connectedCallback=function(){if(r&&r.call(this),this.shadowRoot){let e=document.createElement(`style`);e.appendChild(document.createTextNode(`fieldset[data-v-13a7a1b6]{display:contents}fieldset[disabled][data-v-13a7a1b6]>*{pointer-events:none}`)),this.shadowRoot.appendChild(e)}},e.call(window.customElements,t,n)}}}}catch(e){console.error(`vite-plugin-css-injected-by-js`,e)}})();
|
|
2
|
-
(function(){try{if(typeof document<`u`){var e=document.createElement(`style`);if(e.appendChild(document.createTextNode(`fieldset[data-v-13a7a1b6]{display:contents}fieldset[disabled][data-v-13a7a1b6]>*{pointer-events:none}`)),document.head.appendChild(e),window.customElements){let e=window.customElements.define;window.customElements.define=function(t,n){let r=n.prototype.connectedCallback;return n.prototype.connectedCallback=function(){if(r&&r.call(this),this.shadowRoot){let e=document.createElement(`style`);e.appendChild(document.createTextNode(`fieldset[data-v-13a7a1b6]{display:contents}fieldset[disabled][data-v-13a7a1b6]>*{pointer-events:none}`)),this.shadowRoot.appendChild(e)}},e.call(window.customElements,t,n)}}}}catch(e){console.error(`vite-plugin-css-injected-by-js`,e)}})();
|
|
3
|
-
import e from "./vue-components30.es.js";
|
|
4
|
-
import t from "./vue-components45.es.js";
|
|
5
|
-
|
|
6
|
-
//#region src/components/OmegaForm/OmegaWrapper.vue
|
|
7
|
-
var n = /*#__PURE__*/ e(t, [["__scopeId", "data-v-13a7a1b6"]]);
|
|
8
|
-
//#endregion
|
|
9
|
-
export { n as default };
|