@simsustech/quasar-components 0.12.3 → 0.12.5
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/CHANGELOG.md +30 -0
- package/dist/form.js +130 -122
- package/dist/md3.js +19 -9
- package/dist/quasar-components.css +38 -0
- package/dist/types/src/ui/form/DateInput.vue.d.ts +2 -2
- package/package.json +1 -1
- package/src/ui/form/CronScheduleInput.vue +23 -5
- package/src/ui/form/DateInput.vue +163 -138
- package/src/ui/md3/Md3Layout.vue +55 -57
- package/src/ui/md3/NavigationRailFabs.vue +10 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,35 @@
|
|
|
1
1
|
# @simsustech/quasar-components
|
|
2
2
|
|
|
3
|
+
## 0.12.5
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- d6f5de7: fix(components): fix NavigationRailFabs
|
|
8
|
+
- 0ec347b: fix(CronScheduleInput): remove negative-margin hack, use items-center
|
|
9
|
+
|
|
10
|
+
Same pattern as DateInput: the old margin-top: -1.7em hack broke with
|
|
11
|
+
unocss-preset-quasar updates. Replaced with:
|
|
12
|
+
|
|
13
|
+
- items-center for proper vertical alignment
|
|
14
|
+
- CSS overrides for padding leaks from q-field--labeled
|
|
15
|
+
- Neutralized cascaded padding-top on inner control-containers
|
|
16
|
+
- Removed horizontal padding on inner controls
|
|
17
|
+
|
|
18
|
+
- fix(DateInput): prevent DD/MM/YYYY fields from overlapping QField stack label
|
|
19
|
+
|
|
20
|
+
Nesting QInput inside the outer QField's #control slot created a
|
|
21
|
+
QField-inside-QField structure that caused padding leaks from the
|
|
22
|
+
preset's q-field--labeled descendant selectors and broke with the
|
|
23
|
+
unocss-preset-quasar update. Refactored to use plain `<input>`
|
|
24
|
+
elements instead of nested QInput, removing the old negative-margin
|
|
25
|
+
hack (-1.7em) that caused the overlap.
|
|
26
|
+
|
|
27
|
+
## 0.12.4
|
|
28
|
+
|
|
29
|
+
### Patch Changes
|
|
30
|
+
|
|
31
|
+
- a21d944: fix(components): move ready check to QLayout in Md3Layout
|
|
32
|
+
|
|
3
33
|
## 0.12.3
|
|
4
34
|
|
|
5
35
|
### Patch Changes
|
package/dist/form.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { n as loadLang, r as useLang, t as LocaleSelect_default } from "./LocaleSelect-BtwfPrmu.js";
|
|
2
2
|
import { QBtn, QDate, QEditor, QField, QIcon, QInput, QItem, QItemLabel, QItemSection, QPopupProxy, QSelect, QTooltip, useQuasar } from "quasar";
|
|
3
|
-
import { Fragment, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createSlots, createTextVNode, createVNode, defineComponent, guardReactiveProps, mergeProps, normalizeProps, openBlock, ref, renderList, renderSlot, resolveDirective,
|
|
3
|
+
import { Fragment, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createSlots, createTextVNode, createVNode, defineComponent, guardReactiveProps, mergeProps, normalizeClass, normalizeProps, normalizeStyle, openBlock, ref, renderList, renderSlot, resolveDirective, toDisplayString, toRefs, unref, useAttrs, useSlots, watch, withAsyncContext, withCtx, withDirectives } from "vue";
|
|
4
4
|
//#endregion
|
|
5
5
|
//#region src/ui/form/GenderSelect.vue
|
|
6
6
|
var GenderSelect_default = /* @__PURE__ */ defineComponent({
|
|
@@ -249,15 +249,28 @@ var TelephoneNumberInput_default = /* @__PURE__ */ defineComponent({
|
|
|
249
249
|
});
|
|
250
250
|
//#endregion
|
|
251
251
|
//#region src/ui/form/DateInput.vue?vue&type=script&setup=true&lang.ts
|
|
252
|
-
var _hoisted_1$2 = {
|
|
253
|
-
|
|
252
|
+
var _hoisted_1$2 = {
|
|
253
|
+
class: "row items-center date-input-row no-wrap",
|
|
254
|
+
style: { "height": "100%" }
|
|
255
|
+
};
|
|
256
|
+
var _hoisted_2$1 = [
|
|
257
|
+
"value",
|
|
258
|
+
"placeholder",
|
|
259
|
+
"maxlength",
|
|
260
|
+
"onInput",
|
|
261
|
+
"onKeydown"
|
|
262
|
+
];
|
|
263
|
+
var _hoisted_3 = {
|
|
254
264
|
key: 0,
|
|
265
|
+
class: "q-field__marginal",
|
|
255
266
|
style: {
|
|
256
|
-
"
|
|
257
|
-
"width": "1ch"
|
|
267
|
+
"flex": "initial",
|
|
268
|
+
"width": "1ch",
|
|
269
|
+
"padding": "0",
|
|
270
|
+
"margin": "0"
|
|
258
271
|
}
|
|
259
272
|
};
|
|
260
|
-
var
|
|
273
|
+
var _hoisted_4 = { class: "row items-center justify-end" };
|
|
261
274
|
//#endregion
|
|
262
275
|
//#region src/ui/form/DateInput.vue
|
|
263
276
|
var DateInput_default = /* @__PURE__ */ defineComponent({
|
|
@@ -281,46 +294,84 @@ var DateInput_default = /* @__PURE__ */ defineComponent({
|
|
|
281
294
|
const emit = __emit;
|
|
282
295
|
const lang = useLang();
|
|
283
296
|
const { modelValue, format, locale } = toRefs(props);
|
|
284
|
-
const year = ref();
|
|
285
|
-
const month = ref();
|
|
286
|
-
const day = ref();
|
|
287
|
-
const
|
|
288
|
-
const
|
|
289
|
-
|
|
290
|
-
|
|
297
|
+
const year = ref("");
|
|
298
|
+
const month = ref("");
|
|
299
|
+
const day = ref("");
|
|
300
|
+
const parts = computed(() => {
|
|
301
|
+
const keys = format.value.split("-");
|
|
302
|
+
const map = {
|
|
303
|
+
YYYY: {
|
|
304
|
+
value: year.value,
|
|
305
|
+
placeholder: lang.value.datePicker.YYYY,
|
|
306
|
+
style: { "max-width": format.value === "YYYY-MM-DD" ? "8ch" : "7ch" },
|
|
307
|
+
inputClass: "text-center",
|
|
308
|
+
maxLength: 10
|
|
309
|
+
},
|
|
310
|
+
MM: {
|
|
311
|
+
value: month.value,
|
|
312
|
+
placeholder: lang.value.datePicker.MM,
|
|
313
|
+
style: { "max-width": "7ch" },
|
|
314
|
+
inputClass: "text-center",
|
|
315
|
+
maxLength: 10
|
|
316
|
+
},
|
|
317
|
+
DD: {
|
|
318
|
+
value: day.value,
|
|
319
|
+
placeholder: lang.value.datePicker.DD,
|
|
320
|
+
style: { "max-width": format.value === "DD-MM-YYYY" ? "7ch" : "4ch" },
|
|
321
|
+
inputClass: "text-center",
|
|
322
|
+
maxLength: 10
|
|
323
|
+
}
|
|
324
|
+
};
|
|
325
|
+
return keys.map((k) => ({
|
|
326
|
+
key: k,
|
|
327
|
+
...map[k]
|
|
328
|
+
}));
|
|
329
|
+
});
|
|
330
|
+
const onInput = (e, key) => {
|
|
331
|
+
const input = e.target;
|
|
332
|
+
const raw = input.value;
|
|
333
|
+
let clamped;
|
|
334
|
+
if (key === "YYYY") clamped = clamp(raw, 4);
|
|
335
|
+
else if (key === "MM") clamped = clamp(raw, 2, 12);
|
|
336
|
+
else if (key === "DD") clamped = clamp(raw, 2, 31);
|
|
337
|
+
else clamped = raw;
|
|
338
|
+
if (input.value !== clamped) input.value = clamped;
|
|
339
|
+
if (key === "YYYY") year.value = clamped;
|
|
340
|
+
else if (key === "MM") month.value = clamped;
|
|
341
|
+
else if (key === "DD") day.value = clamped;
|
|
291
342
|
};
|
|
292
|
-
const
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
343
|
+
const onKeydown = (e, _index) => {
|
|
344
|
+
if (["Minus", "Slash"].includes(e.code)) {
|
|
345
|
+
e.preventDefault();
|
|
346
|
+
const all = e.currentTarget.closest(".date-input-row")?.querySelectorAll(".q-field__native");
|
|
347
|
+
const currentIdx = Array.from(all || []).indexOf(e.currentTarget);
|
|
348
|
+
(all?.[currentIdx + 1])?.focus();
|
|
349
|
+
}
|
|
296
350
|
};
|
|
297
|
-
const
|
|
298
|
-
const
|
|
299
|
-
if (
|
|
300
|
-
|
|
351
|
+
const clamp = (val, maxLen, maxVal) => {
|
|
352
|
+
const digits = val.replace(/\D/g, "").slice(0, maxLen);
|
|
353
|
+
if (maxVal !== void 0 && digits.length === maxLen) {
|
|
354
|
+
if (parseInt(digits, 10) > maxVal) return String(maxVal);
|
|
355
|
+
}
|
|
356
|
+
return digits;
|
|
301
357
|
};
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
358
|
+
watch(year, () => emitDate());
|
|
359
|
+
watch(month, () => emitDate());
|
|
360
|
+
watch(day, () => emitDate());
|
|
361
|
+
function emitDate() {
|
|
362
|
+
const y = year.value;
|
|
363
|
+
const m = month.value;
|
|
364
|
+
const d = day.value;
|
|
365
|
+
if (y.length === 4 && m.length === 2 && d.length === 2) {
|
|
366
|
+
const date = `${y}-${m}-${d}`;
|
|
367
|
+
if (!isNaN(Date.parse(date))) {
|
|
368
|
+
emit("update:modelValue", date);
|
|
369
|
+
return;
|
|
309
370
|
}
|
|
310
371
|
}
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
};
|
|
315
|
-
watch([
|
|
316
|
-
year,
|
|
317
|
-
month,
|
|
318
|
-
day
|
|
319
|
-
], () => {
|
|
320
|
-
const date = `${year.value}-${String(month.value).padStart(2, "0")}-${String(day.value).padStart(2, "0")}`;
|
|
321
|
-
if (year.value && month.value && day.value && !isNaN(Date.parse(date))) emit("update:modelValue", date);
|
|
322
|
-
else if (modelValue.value !== null) emit("update:modelValue", null);
|
|
323
|
-
});
|
|
372
|
+
const partial = `${y.padEnd(4, "_")}-${m.padEnd(2, "_")}-${d.padEnd(2, "_")}`;
|
|
373
|
+
if (partial !== modelValue.value) emit("update:modelValue", partial);
|
|
374
|
+
}
|
|
324
375
|
const formattedDate = computed(() => {
|
|
325
376
|
if (modelValue.value) return new Date(Date.parse(modelValue.value)).toLocaleDateString(locale.value, {
|
|
326
377
|
weekday: "long",
|
|
@@ -330,69 +381,28 @@ var DateInput_default = /* @__PURE__ */ defineComponent({
|
|
|
330
381
|
});
|
|
331
382
|
return "";
|
|
332
383
|
});
|
|
384
|
+
function setInternalDate(dateString, separator = "-") {
|
|
385
|
+
if (dateString) {
|
|
386
|
+
const [yearPart, monthPart, dayPart] = dateString.split(separator);
|
|
387
|
+
if (yearPart && monthPart && dayPart) {
|
|
388
|
+
year.value = String(yearPart);
|
|
389
|
+
month.value = String(monthPart).padStart(2, "0");
|
|
390
|
+
day.value = String(dayPart).padStart(2, "0");
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
const setDate = (value) => {
|
|
395
|
+
setInternalDate(value, "/");
|
|
396
|
+
};
|
|
333
397
|
watch(modelValue, (newVal) => {
|
|
334
|
-
if (newVal) setInternalDate(newVal);
|
|
398
|
+
if (newVal && !newVal.includes("_")) setInternalDate(newVal);
|
|
335
399
|
else if (newVal === null) {
|
|
336
|
-
year.value =
|
|
337
|
-
month.value =
|
|
338
|
-
day.value =
|
|
400
|
+
year.value = "";
|
|
401
|
+
month.value = "";
|
|
402
|
+
day.value = "";
|
|
339
403
|
}
|
|
340
404
|
});
|
|
341
405
|
setInternalDate(modelValue.value);
|
|
342
|
-
const goToNextElement = (e) => {
|
|
343
|
-
if (["Minus", "Slash"].includes(e.code)) {
|
|
344
|
-
e.preventDefault();
|
|
345
|
-
const next = e.currentTarget.parentElement?.parentElement?.parentElement?.parentElement?.nextElementSibling;
|
|
346
|
-
if (next) next.focus();
|
|
347
|
-
}
|
|
348
|
-
};
|
|
349
|
-
const dateProps = computed(() => ({
|
|
350
|
-
YYYY: {
|
|
351
|
-
modelValue: year.value,
|
|
352
|
-
placeholder: lang.value.datePicker.YYYY,
|
|
353
|
-
style: {
|
|
354
|
-
"max-width": format.value === "YYYY-MM-DD" ? "8ch" : "7ch",
|
|
355
|
-
"margin-top": "-1.7em",
|
|
356
|
-
"margin-bottom": "-0.5em",
|
|
357
|
-
background: "transparent",
|
|
358
|
-
border: 0
|
|
359
|
-
},
|
|
360
|
-
class: format.value !== "YYYY-MM-DD" ? "q-mb-none q-ml-none" : void 0,
|
|
361
|
-
inputClass: "text-center",
|
|
362
|
-
"onUpdate:modelValue": setYear,
|
|
363
|
-
onKeydown: goToNextElement
|
|
364
|
-
},
|
|
365
|
-
MM: {
|
|
366
|
-
modelValue: month.value ? String(month.value).padStart(2, "0") : "",
|
|
367
|
-
placeholder: lang.value.datePicker.MM,
|
|
368
|
-
style: {
|
|
369
|
-
"max-width": "7ch",
|
|
370
|
-
"margin-top": "-1.7em",
|
|
371
|
-
"margin-bottom": "-0.5em",
|
|
372
|
-
background: "transparent",
|
|
373
|
-
border: 0
|
|
374
|
-
},
|
|
375
|
-
class: "q-ml-none",
|
|
376
|
-
inputClass: "text-center",
|
|
377
|
-
"onUpdate:modelValue": setMonth,
|
|
378
|
-
onKeydown: goToNextElement
|
|
379
|
-
},
|
|
380
|
-
DD: {
|
|
381
|
-
modelValue: day.value ? String(day.value).padStart(2, "0") : "",
|
|
382
|
-
placeholder: lang.value.datePicker.DD,
|
|
383
|
-
style: {
|
|
384
|
-
"max-width": format.value === "DD-MM-YYYY" ? "7ch" : "4ch",
|
|
385
|
-
"margin-top": "-1.7em",
|
|
386
|
-
"margin-bottom": "-0.5em",
|
|
387
|
-
background: "transparent",
|
|
388
|
-
border: 0
|
|
389
|
-
},
|
|
390
|
-
class: format.value === "YYYY-MM-DD" ? "q-ml-none" : void 0,
|
|
391
|
-
inputClass: "text-center",
|
|
392
|
-
"onUpdate:modelValue": setDay,
|
|
393
|
-
onKeydown: goToNextElement
|
|
394
|
-
}
|
|
395
|
-
}));
|
|
396
406
|
const validations = ref([(v) => {
|
|
397
407
|
if (v !== null) return /^\d{4}-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])$/.test(v);
|
|
398
408
|
return true;
|
|
@@ -411,24 +421,24 @@ var DateInput_default = /* @__PURE__ */ defineComponent({
|
|
|
411
421
|
rules: validations.value,
|
|
412
422
|
label: `${__props.label}${__props.required ? "*" : ""}`,
|
|
413
423
|
"stack-label": "",
|
|
414
|
-
"lazy-rules": ""
|
|
424
|
+
"lazy-rules": "",
|
|
425
|
+
class: "date-input-field"
|
|
415
426
|
}, createSlots({
|
|
416
|
-
control: withCtx(() => [createElementVNode("div", _hoisted_1$2, [(openBlock(true), createElementBlock(Fragment, null, renderList(
|
|
417
|
-
return openBlock(),
|
|
418
|
-
key: part,
|
|
419
|
-
class: "
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
427
|
+
control: withCtx(() => [createElementVNode("div", _hoisted_1$2, [(openBlock(true), createElementBlock(Fragment, null, renderList(parts.value, (part, index) => {
|
|
428
|
+
return openBlock(), createElementBlock("div", {
|
|
429
|
+
key: part.key,
|
|
430
|
+
class: "row no-wrap items-center",
|
|
431
|
+
style: { "gap": "0" }
|
|
432
|
+
}, [createElementVNode("input", {
|
|
433
|
+
value: part.value,
|
|
434
|
+
placeholder: part.placeholder,
|
|
435
|
+
class: normalizeClass(["q-field__native text-center", part.inputClass]),
|
|
436
|
+
style: normalizeStyle(part.style),
|
|
426
437
|
inputmode: "numeric",
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
}, 1040);
|
|
438
|
+
maxlength: part.maxLength,
|
|
439
|
+
onInput: ($event) => onInput($event, part.key),
|
|
440
|
+
onKeydown: ($event) => onKeydown($event, index)
|
|
441
|
+
}, null, 46, _hoisted_2$1), index < parts.value.length - 1 ? (openBlock(), createElementBlock("span", _hoisted_3, "-")) : createCommentVNode("", true)]);
|
|
432
442
|
}), 128))])]),
|
|
433
443
|
append: withCtx(() => [__props.clearable ? (openBlock(), createBlock(_component_q_icon, {
|
|
434
444
|
key: 0,
|
|
@@ -451,7 +461,7 @@ var DateInput_default = /* @__PURE__ */ defineComponent({
|
|
|
451
461
|
"model-value": unref(modelValue)?.replaceAll("-", "/"),
|
|
452
462
|
"onUpdate:modelValue": setDate
|
|
453
463
|
}), {
|
|
454
|
-
default: withCtx(() => [createElementVNode("div",
|
|
464
|
+
default: withCtx(() => [createElementVNode("div", _hoisted_4, [withDirectives(createVNode(_component_q_btn, {
|
|
455
465
|
label: unref(lang).buttons.close,
|
|
456
466
|
color: "primary",
|
|
457
467
|
flat: ""
|
|
@@ -805,10 +815,10 @@ var FilteredModelSelect_default = /* @__PURE__ */ defineComponent({
|
|
|
805
815
|
});
|
|
806
816
|
//#endregion
|
|
807
817
|
//#region src/ui/form/CronScheduleInput.vue?vue&type=script&setup=true&lang.ts
|
|
808
|
-
var _hoisted_1$1 = { class: "row" };
|
|
818
|
+
var _hoisted_1$1 = { class: "row cron-input-row items-center" };
|
|
809
819
|
var _hoisted_2 = {
|
|
810
820
|
key: 0,
|
|
811
|
-
class: "row"
|
|
821
|
+
class: "row cron-input-row items-center"
|
|
812
822
|
};
|
|
813
823
|
//#endregion
|
|
814
824
|
//#region src/ui/form/CronScheduleInput.vue
|
|
@@ -869,13 +879,10 @@ var CronScheduleInput_default = /* @__PURE__ */ defineComponent({
|
|
|
869
879
|
}
|
|
870
880
|
}
|
|
871
881
|
const smallStyle = {
|
|
872
|
-
"margin-top": "-1.7em",
|
|
873
|
-
"margin-bottom": "-0.5em",
|
|
874
882
|
background: "transparent",
|
|
875
883
|
border: 0
|
|
876
884
|
};
|
|
877
885
|
const dayOfWeekStyle = {
|
|
878
|
-
"margin-bottom": "-0.5em",
|
|
879
886
|
background: "transparent",
|
|
880
887
|
border: 0
|
|
881
888
|
};
|
|
@@ -892,7 +899,8 @@ var CronScheduleInput_default = /* @__PURE__ */ defineComponent({
|
|
|
892
899
|
rules: validations.value,
|
|
893
900
|
label: `${unref(label)}${__props.required ? "*" : ""}`,
|
|
894
901
|
"stack-label": "",
|
|
895
|
-
borderless: ""
|
|
902
|
+
borderless: "",
|
|
903
|
+
class: "cron-input-field"
|
|
896
904
|
}, {
|
|
897
905
|
control: withCtx(() => [createElementVNode("div", _hoisted_1$1, [
|
|
898
906
|
__props.showHour ? (openBlock(), createBlock(_component_q_select, {
|
package/dist/md3.js
CHANGED
|
@@ -32,7 +32,11 @@ var NavigationRailFabs_default = /* @__PURE__ */ defineComponent({
|
|
|
32
32
|
"gt-sm": true,
|
|
33
33
|
animated: !!__props.seekAttention,
|
|
34
34
|
"animated-tada": !!__props.seekAttention,
|
|
35
|
-
"animated-infinite": !!__props.seekAttention
|
|
35
|
+
"animated-infinite": !!__props.seekAttention,
|
|
36
|
+
"!bg-$light-primary-container": true,
|
|
37
|
+
"dark:!bg-$dark-primary-container": true,
|
|
38
|
+
"text-$on-light-primary-container": true,
|
|
39
|
+
"dark:text-$on-dark-primary-container": true
|
|
36
40
|
}),
|
|
37
41
|
fab: "",
|
|
38
42
|
icon: unref(addIcon),
|
|
@@ -49,7 +53,11 @@ var NavigationRailFabs_default = /* @__PURE__ */ defineComponent({
|
|
|
49
53
|
"gt-sm": true,
|
|
50
54
|
animated: !!__props.seekAttention,
|
|
51
55
|
"animated-tada": !!__props.seekAttention,
|
|
52
|
-
"animated-infinite": !!__props.seekAttention
|
|
56
|
+
"animated-infinite": !!__props.seekAttention,
|
|
57
|
+
"!bg-$light-primary-container": true,
|
|
58
|
+
"dark:!bg-$dark-primary-container": true,
|
|
59
|
+
"text-$on-light-primary-container": true,
|
|
60
|
+
"dark:text-$on-dark-primary-container": true
|
|
53
61
|
}),
|
|
54
62
|
fab: "",
|
|
55
63
|
icon: unref(editIcon),
|
|
@@ -264,8 +272,7 @@ function onClickOutside(target, handler, options = {}) {
|
|
|
264
272
|
Number.POSITIVE_INFINITY;
|
|
265
273
|
//#endregion
|
|
266
274
|
//#region src/ui/md3/Md3Layout.vue?vue&type=script&setup=true&lang.ts
|
|
267
|
-
var _hoisted_1 = {
|
|
268
|
-
var _hoisted_2 = {
|
|
275
|
+
var _hoisted_1 = {
|
|
269
276
|
id: "fabs",
|
|
270
277
|
class: "q-mb-md min-h-56px"
|
|
271
278
|
};
|
|
@@ -325,8 +332,11 @@ var Md3Layout_default = /* @__PURE__ */ defineComponent({
|
|
|
325
332
|
const _component_router_view = resolveComponent("router-view");
|
|
326
333
|
const _component_q_page_container = QPageContainer;
|
|
327
334
|
const _component_q_layout = QLayout;
|
|
328
|
-
return openBlock(), createBlock(_component_q_layout, {
|
|
329
|
-
|
|
335
|
+
return __props.ready ? (openBlock(), createBlock(_component_q_layout, {
|
|
336
|
+
key: 0,
|
|
337
|
+
view: "lHh Lpr lFf"
|
|
338
|
+
}, {
|
|
339
|
+
default: withCtx(() => [
|
|
330
340
|
createVNode(_component_q_header, null, {
|
|
331
341
|
default: withCtx(() => [createVNode(_component_q_toolbar, null, {
|
|
332
342
|
default: withCtx(() => [!miniState.value ? (openBlock(), createBlock(_component_q_btn, {
|
|
@@ -369,7 +379,7 @@ var Md3Layout_default = /* @__PURE__ */ defineComponent({
|
|
|
369
379
|
class: "q-mb-md",
|
|
370
380
|
onClick: _cache[1] || (_cache[1] = ($event) => toggleLeftDrawer())
|
|
371
381
|
}),
|
|
372
|
-
createElementVNode("div",
|
|
382
|
+
createElementVNode("div", _hoisted_1, [renderSlot(_ctx.$slots, "fabs", { showSticky: false })]),
|
|
373
383
|
renderSlot(_ctx.$slots, "drawer-mini-navigation")
|
|
374
384
|
], 2)]),
|
|
375
385
|
default: withCtx(() => [renderSlot(_ctx.$slots, "drawer")]),
|
|
@@ -387,9 +397,9 @@ var Md3Layout_default = /* @__PURE__ */ defineComponent({
|
|
|
387
397
|
default: withCtx(() => [createVNode(_component_router_view), renderSlot(_ctx.$slots, "fabs", { showSticky: true })]),
|
|
388
398
|
_: 3
|
|
389
399
|
})
|
|
390
|
-
])
|
|
400
|
+
]),
|
|
391
401
|
_: 3
|
|
392
|
-
});
|
|
402
|
+
})) : createCommentVNode("", true);
|
|
393
403
|
};
|
|
394
404
|
}
|
|
395
405
|
});
|
|
@@ -2,6 +2,44 @@
|
|
|
2
2
|
.break-all {
|
|
3
3
|
word-break: break-all;
|
|
4
4
|
}
|
|
5
|
+
|
|
6
|
+
/* The outer QField gets q-field--labeled which leaks padding into
|
|
7
|
+
descendant .q-field__native elements. The auto-height override
|
|
8
|
+
fixes padding-top but not padding-bottom. */
|
|
9
|
+
.date-input-field.q-field--auto-height.q-field--labeled .q-field__native {
|
|
10
|
+
padding-bottom: 0 !important;
|
|
11
|
+
box-sizing: border-box;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/* Remove the standard underline (creates whitespace beneath) */
|
|
15
|
+
.date-input-field.q-field--standard
|
|
16
|
+
> .q-field__inner
|
|
17
|
+
> .q-field__control::before {
|
|
18
|
+
border-bottom: none !important;
|
|
19
|
+
}
|
|
20
|
+
.date-input-field.q-field--standard
|
|
21
|
+
> .q-field__inner
|
|
22
|
+
> .q-field__control::after {
|
|
23
|
+
display: none !important;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/* Stop padding leak from outer q-field--labeled into inner QSelects */
|
|
27
|
+
.cron-input-field.q-field--labeled .cron-input-row .q-field__native,
|
|
28
|
+
.cron-input-field.q-field--labeled .cron-input-row .q-field__input {
|
|
29
|
+
padding-bottom: 0 !important;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/* Inner control-container — neutralize cascaded padding-top */
|
|
33
|
+
.cron-input-field.q-field--auto-height.q-field--labeled
|
|
34
|
+
.cron-input-row
|
|
35
|
+
.q-field__control-container {
|
|
36
|
+
padding-top: 0 !important;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/* Inner controls — remove horizontal padding */
|
|
40
|
+
.cron-input-field .cron-input-row .q-field__control {
|
|
41
|
+
padding-inline: 0 !important;
|
|
42
|
+
}
|
|
5
43
|
/* https://github.com/quasarframework/quasar/blob/dev/docs/src/layouts/doc-layout/DocPageMenu.sass */
|
|
6
44
|
.q-drawer-list .q-item__section--avatar {
|
|
7
45
|
color: var(--q-primary);
|
|
@@ -12,9 +12,9 @@ export interface Props {
|
|
|
12
12
|
clear: string;
|
|
13
13
|
};
|
|
14
14
|
}
|
|
15
|
-
declare var
|
|
15
|
+
declare var __VLS_50: string, __VLS_51: any;
|
|
16
16
|
type __VLS_Slots = {} & {
|
|
17
|
-
[K in NonNullable<typeof
|
|
17
|
+
[K in NonNullable<typeof __VLS_50>]?: (props: typeof __VLS_51) => any;
|
|
18
18
|
};
|
|
19
19
|
declare const __VLS_base: import("vue").DefineComponent<Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
|
|
20
20
|
"update:modelValue": (val: string | null) => any;
|
package/package.json
CHANGED
|
@@ -5,9 +5,10 @@
|
|
|
5
5
|
:label="`${label}${required ? '*' : ''}`"
|
|
6
6
|
stack-label
|
|
7
7
|
borderless
|
|
8
|
+
class="cron-input-field"
|
|
8
9
|
>
|
|
9
10
|
<template #control>
|
|
10
|
-
<div class="row">
|
|
11
|
+
<div class="row cron-input-row items-center">
|
|
11
12
|
<q-select
|
|
12
13
|
v-if="showHour"
|
|
13
14
|
v-model="hour"
|
|
@@ -102,7 +103,7 @@
|
|
|
102
103
|
</template>
|
|
103
104
|
</q-select>
|
|
104
105
|
</div>
|
|
105
|
-
<div v-if="showDayOfWeek" class="row">
|
|
106
|
+
<div v-if="showDayOfWeek" class="row cron-input-row items-center">
|
|
106
107
|
<q-select
|
|
107
108
|
v-if="showDayOfWeek"
|
|
108
109
|
v-model="dayOfWeek"
|
|
@@ -214,14 +215,11 @@ function setInternalCron(cronString: string) {
|
|
|
214
215
|
}
|
|
215
216
|
|
|
216
217
|
const smallStyle = {
|
|
217
|
-
'margin-top': '-1.7em',
|
|
218
|
-
'margin-bottom': '-0.5em',
|
|
219
218
|
background: 'transparent',
|
|
220
219
|
border: 0
|
|
221
220
|
}
|
|
222
221
|
|
|
223
222
|
const dayOfWeekStyle = {
|
|
224
|
-
'margin-bottom': '-0.5em',
|
|
225
223
|
background: 'transparent',
|
|
226
224
|
border: 0
|
|
227
225
|
}
|
|
@@ -234,3 +232,23 @@ watch(modelValue, (newVal) => {
|
|
|
234
232
|
})
|
|
235
233
|
setInternalCron(modelValue.value)
|
|
236
234
|
</script>
|
|
235
|
+
|
|
236
|
+
<style>
|
|
237
|
+
/* Stop padding leak from outer q-field--labeled into inner QSelects */
|
|
238
|
+
.cron-input-field.q-field--labeled .cron-input-row .q-field__native,
|
|
239
|
+
.cron-input-field.q-field--labeled .cron-input-row .q-field__input {
|
|
240
|
+
padding-bottom: 0 !important;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/* Inner control-container — neutralize cascaded padding-top */
|
|
244
|
+
.cron-input-field.q-field--auto-height.q-field--labeled
|
|
245
|
+
.cron-input-row
|
|
246
|
+
.q-field__control-container {
|
|
247
|
+
padding-top: 0 !important;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/* Inner controls — remove horizontal padding */
|
|
251
|
+
.cron-input-field .cron-input-row .q-field__control {
|
|
252
|
+
padding-inline: 0 !important;
|
|
253
|
+
}
|
|
254
|
+
</style>
|
|
@@ -6,27 +6,34 @@
|
|
|
6
6
|
:label="`${label}${required ? '*' : ''}`"
|
|
7
7
|
stack-label
|
|
8
8
|
lazy-rules
|
|
9
|
+
class="date-input-field"
|
|
9
10
|
>
|
|
10
11
|
<template #control>
|
|
11
|
-
<div class="row">
|
|
12
|
-
<
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
borderless
|
|
18
|
-
:filled="false"
|
|
19
|
-
:outlined="false"
|
|
20
|
-
:standout="false"
|
|
21
|
-
:rounded="false"
|
|
22
|
-
v-bind="dateProps[part]"
|
|
23
|
-
inputmode="numeric"
|
|
24
|
-
dense
|
|
12
|
+
<div class="row items-center date-input-row no-wrap" style="height: 100%">
|
|
13
|
+
<div
|
|
14
|
+
v-for="(part, index) in parts"
|
|
15
|
+
:key="part.key"
|
|
16
|
+
class="row no-wrap items-center"
|
|
17
|
+
style="gap: 0"
|
|
25
18
|
>
|
|
26
|
-
<
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
19
|
+
<input
|
|
20
|
+
:value="part.value"
|
|
21
|
+
:placeholder="part.placeholder"
|
|
22
|
+
class="q-field__native text-center"
|
|
23
|
+
:class="part.inputClass"
|
|
24
|
+
:style="part.style"
|
|
25
|
+
inputmode="numeric"
|
|
26
|
+
:maxlength="part.maxLength"
|
|
27
|
+
@input="onInput($event, part.key)"
|
|
28
|
+
@keydown="onKeydown($event, index)"
|
|
29
|
+
/>
|
|
30
|
+
<span
|
|
31
|
+
v-if="index < parts.length - 1"
|
|
32
|
+
class="q-field__marginal"
|
|
33
|
+
style="flex: initial; width: 1ch; padding: 0; margin: 0"
|
|
34
|
+
>-</span
|
|
35
|
+
>
|
|
36
|
+
</div>
|
|
30
37
|
</div>
|
|
31
38
|
</template>
|
|
32
39
|
|
|
@@ -68,13 +75,7 @@
|
|
|
68
75
|
|
|
69
76
|
<script setup lang="ts">
|
|
70
77
|
import { ref, watch, toRefs, computed } from 'vue'
|
|
71
|
-
import {
|
|
72
|
-
QDate,
|
|
73
|
-
QDateProps,
|
|
74
|
-
QInput,
|
|
75
|
-
QInputProps,
|
|
76
|
-
QuasarLanguageCodes
|
|
77
|
-
} from 'quasar'
|
|
78
|
+
import { QDate, QDateProps, QuasarLanguageCodes } from 'quasar'
|
|
78
79
|
import { useLang } from './lang'
|
|
79
80
|
|
|
80
81
|
export interface Props {
|
|
@@ -103,68 +104,112 @@ const props = withDefaults(defineProps<Props>(), {
|
|
|
103
104
|
const emit = defineEmits<{
|
|
104
105
|
(e: 'update:modelValue', val: string | null): void
|
|
105
106
|
}>()
|
|
106
|
-
// const attrs = useAttrs()
|
|
107
107
|
|
|
108
108
|
const lang = useLang()
|
|
109
109
|
|
|
110
110
|
const { modelValue, format, locale } = toRefs(props)
|
|
111
111
|
|
|
112
|
-
const year = ref
|
|
113
|
-
const month = ref
|
|
114
|
-
const day = ref
|
|
112
|
+
const year = ref('')
|
|
113
|
+
const month = ref('')
|
|
114
|
+
const day = ref('')
|
|
115
115
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
116
|
+
interface PartInfo {
|
|
117
|
+
value: string
|
|
118
|
+
placeholder: string
|
|
119
|
+
style: Record<string, string>
|
|
120
|
+
inputClass: string
|
|
121
|
+
maxLength: number
|
|
122
122
|
}
|
|
123
123
|
|
|
124
|
-
const
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
}
|
|
124
|
+
const parts = computed(() => {
|
|
125
|
+
const keys = format.value.split('-')
|
|
126
|
+
const map: Record<string, PartInfo> = {
|
|
127
|
+
YYYY: {
|
|
128
|
+
value: year.value,
|
|
129
|
+
placeholder: lang.value.datePicker.YYYY,
|
|
130
|
+
style: { 'max-width': format.value === 'YYYY-MM-DD' ? '8ch' : '7ch' },
|
|
131
|
+
inputClass: 'text-center',
|
|
132
|
+
maxLength: 10
|
|
133
|
+
},
|
|
134
|
+
MM: {
|
|
135
|
+
value: month.value,
|
|
136
|
+
placeholder: lang.value.datePicker.MM,
|
|
137
|
+
style: { 'max-width': '7ch' },
|
|
138
|
+
inputClass: 'text-center',
|
|
139
|
+
maxLength: 10
|
|
140
|
+
},
|
|
141
|
+
DD: {
|
|
142
|
+
value: day.value,
|
|
143
|
+
placeholder: lang.value.datePicker.DD,
|
|
144
|
+
style: { 'max-width': format.value === 'DD-MM-YYYY' ? '7ch' : '4ch' },
|
|
145
|
+
inputClass: 'text-center',
|
|
146
|
+
maxLength: 10
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
return keys.map((k) => ({ key: k, ...map[k] }))
|
|
150
|
+
})
|
|
131
151
|
|
|
132
|
-
const
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
if (
|
|
137
|
-
else
|
|
152
|
+
const onInput = (e: Event, key: string) => {
|
|
153
|
+
const input = e.target as HTMLInputElement
|
|
154
|
+
const raw = input.value
|
|
155
|
+
let clamped: string
|
|
156
|
+
if (key === 'YYYY') clamped = clamp(raw, 4)
|
|
157
|
+
else if (key === 'MM') clamped = clamp(raw, 2, 12)
|
|
158
|
+
else if (key === 'DD') clamped = clamp(raw, 2, 31)
|
|
159
|
+
else clamped = raw
|
|
160
|
+
// Directly set DOM value so it's visible immediately — Vue's :value
|
|
161
|
+
// binding is async and `pressSequentially` types faster than it resolves.
|
|
162
|
+
// Without this, the browser shows the raw non-digit-mixed value between renders.
|
|
163
|
+
if (input.value !== clamped) input.value = clamped
|
|
164
|
+
if (key === 'YYYY') year.value = clamped
|
|
165
|
+
else if (key === 'MM') month.value = clamped
|
|
166
|
+
else if (key === 'DD') day.value = clamped
|
|
138
167
|
}
|
|
139
168
|
|
|
140
|
-
const
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
const
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
}
|
|
169
|
+
const onKeydown = (e: KeyboardEvent, _index: number) => {
|
|
170
|
+
if (['Minus', 'Slash'].includes(e.code)) {
|
|
171
|
+
e.preventDefault()
|
|
172
|
+
const row = (e.currentTarget as HTMLElement).closest('.date-input-row')
|
|
173
|
+
const all = row?.querySelectorAll('.q-field__native')
|
|
174
|
+
const currentIdx = Array.from(all || []).indexOf(
|
|
175
|
+
e.currentTarget as HTMLElement
|
|
176
|
+
)
|
|
177
|
+
const next = all?.[currentIdx + 1] as HTMLElement | undefined
|
|
178
|
+
next?.focus()
|
|
151
179
|
}
|
|
152
180
|
}
|
|
153
181
|
|
|
154
|
-
const
|
|
155
|
-
|
|
156
|
-
)
|
|
157
|
-
|
|
182
|
+
const clamp = (val: string, maxLen: number, maxVal?: number): string => {
|
|
183
|
+
const digits = val.replace(/\D/g, '').slice(0, maxLen)
|
|
184
|
+
if (maxVal !== undefined && digits.length === maxLen) {
|
|
185
|
+
const n = parseInt(digits, 10)
|
|
186
|
+
if (n > maxVal) return String(maxVal)
|
|
187
|
+
}
|
|
188
|
+
return digits
|
|
158
189
|
}
|
|
159
190
|
|
|
160
|
-
watch(
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
191
|
+
watch(year, () => emitDate())
|
|
192
|
+
watch(month, () => emitDate())
|
|
193
|
+
watch(day, () => emitDate())
|
|
194
|
+
|
|
195
|
+
function emitDate() {
|
|
196
|
+
const y = year.value
|
|
197
|
+
const m = month.value
|
|
198
|
+
const d = day.value
|
|
199
|
+
if (y.length === 4 && m.length === 2 && d.length === 2) {
|
|
200
|
+
const date = `${y}-${m}-${d}`
|
|
201
|
+
if (!isNaN(Date.parse(date))) {
|
|
202
|
+
emit('update:modelValue', date)
|
|
203
|
+
return
|
|
204
|
+
}
|
|
166
205
|
}
|
|
167
|
-
|
|
206
|
+
// Emit partial date so validation rules still catch invalid input,
|
|
207
|
+
// but watch(modelValue) doesn't clear the refs (it only clears on null).
|
|
208
|
+
const partial = `${y.padEnd(4, '_')}-${m.padEnd(2, '_')}-${d.padEnd(2, '_')}`
|
|
209
|
+
if (partial !== modelValue.value) {
|
|
210
|
+
emit('update:modelValue', partial)
|
|
211
|
+
}
|
|
212
|
+
}
|
|
168
213
|
|
|
169
214
|
const formattedDate = computed(() => {
|
|
170
215
|
if (modelValue.value)
|
|
@@ -180,82 +225,42 @@ const formattedDate = computed(() => {
|
|
|
180
225
|
return ''
|
|
181
226
|
})
|
|
182
227
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
const goToNextElement = (e: KeyboardEvent) => {
|
|
194
|
-
if (['Minus', 'Slash'].includes(e.code)) {
|
|
195
|
-
e.preventDefault()
|
|
196
|
-
const next = (e.currentTarget as HTMLElement).parentElement?.parentElement
|
|
197
|
-
?.parentElement?.parentElement?.nextElementSibling
|
|
198
|
-
if (next) {
|
|
199
|
-
;(next as HTMLElement).focus()
|
|
228
|
+
function setInternalDate(
|
|
229
|
+
dateString?: string | null,
|
|
230
|
+
separator: '-' | '/' = '-'
|
|
231
|
+
) {
|
|
232
|
+
if (dateString) {
|
|
233
|
+
const [yearPart, monthPart, dayPart] = dateString.split(separator)
|
|
234
|
+
if (yearPart && monthPart && dayPart) {
|
|
235
|
+
year.value = String(yearPart)
|
|
236
|
+
month.value = String(monthPart).padStart(2, '0')
|
|
237
|
+
day.value = String(dayPart).padStart(2, '0')
|
|
200
238
|
}
|
|
201
239
|
}
|
|
202
240
|
}
|
|
203
241
|
|
|
204
|
-
const
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
'onUpdate:modelValue': setYear,
|
|
219
|
-
onKeydown: goToNextElement
|
|
220
|
-
},
|
|
221
|
-
MM: {
|
|
222
|
-
modelValue: month.value ? String(month.value).padStart(2, '0') : '',
|
|
223
|
-
placeholder: lang.value.datePicker.MM,
|
|
224
|
-
style: {
|
|
225
|
-
'max-width': '7ch',
|
|
226
|
-
'margin-top': '-1.7em',
|
|
227
|
-
'margin-bottom': '-0.5em',
|
|
228
|
-
background: 'transparent',
|
|
229
|
-
border: 0
|
|
230
|
-
},
|
|
231
|
-
// suffix: '-',
|
|
232
|
-
class: 'q-ml-none',
|
|
233
|
-
inputClass: 'text-center',
|
|
234
|
-
'onUpdate:modelValue': setMonth,
|
|
235
|
-
onKeydown: goToNextElement
|
|
236
|
-
},
|
|
237
|
-
DD: {
|
|
238
|
-
modelValue: day.value ? String(day.value).padStart(2, '0') : '',
|
|
239
|
-
placeholder: lang.value.datePicker.DD,
|
|
240
|
-
style: {
|
|
241
|
-
'max-width': format.value === 'DD-MM-YYYY' ? '7ch' : '4ch',
|
|
242
|
-
'margin-top': '-1.7em',
|
|
243
|
-
'margin-bottom': '-0.5em',
|
|
244
|
-
background: 'transparent',
|
|
245
|
-
border: 0
|
|
246
|
-
},
|
|
247
|
-
// suffix: format.value === 'DD-MM-YYYY' ? '-' : undefined,
|
|
248
|
-
class: format.value === 'YYYY-MM-DD' ? 'q-ml-none' : undefined,
|
|
249
|
-
inputClass: 'text-center',
|
|
250
|
-
'onUpdate:modelValue': setDay,
|
|
251
|
-
onKeydown: goToNextElement
|
|
242
|
+
const setDate: InstanceType<typeof QDate>['$props']['onUpdate:modelValue'] = (
|
|
243
|
+
value
|
|
244
|
+
) => {
|
|
245
|
+
setInternalDate(value, '/')
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
watch(modelValue, (newVal) => {
|
|
249
|
+
if (newVal && !newVal.includes('_')) {
|
|
250
|
+
// Proper date string (no _ padding from partial emits)
|
|
251
|
+
setInternalDate(newVal)
|
|
252
|
+
} else if (newVal === null) {
|
|
253
|
+
year.value = ''
|
|
254
|
+
month.value = ''
|
|
255
|
+
day.value = ''
|
|
252
256
|
}
|
|
253
|
-
|
|
257
|
+
// Partial dates contain _ — refs are already correct from onInput
|
|
258
|
+
})
|
|
259
|
+
setInternalDate(modelValue.value)
|
|
254
260
|
|
|
255
261
|
const validations = ref<((val: string) => boolean | string)[]>([
|
|
256
262
|
(v) => {
|
|
257
263
|
if (v !== null)
|
|
258
|
-
// return /^\d{4}\/(0?[1-9]|1[012])\/(0?[1-9]|[12][0-9]|3[01])$/.test(v)
|
|
259
264
|
return /^\d{4}-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])$/.test(v)
|
|
260
265
|
return true
|
|
261
266
|
}
|
|
@@ -267,4 +272,24 @@ if (props.required)
|
|
|
267
272
|
)
|
|
268
273
|
</script>
|
|
269
274
|
|
|
270
|
-
<style
|
|
275
|
+
<style>
|
|
276
|
+
/* The outer QField gets q-field--labeled which leaks padding into
|
|
277
|
+
descendant .q-field__native elements. The auto-height override
|
|
278
|
+
fixes padding-top but not padding-bottom. */
|
|
279
|
+
.date-input-field.q-field--auto-height.q-field--labeled .q-field__native {
|
|
280
|
+
padding-bottom: 0 !important;
|
|
281
|
+
box-sizing: border-box;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/* Remove the standard underline (creates whitespace beneath) */
|
|
285
|
+
.date-input-field.q-field--standard
|
|
286
|
+
> .q-field__inner
|
|
287
|
+
> .q-field__control::before {
|
|
288
|
+
border-bottom: none !important;
|
|
289
|
+
}
|
|
290
|
+
.date-input-field.q-field--standard
|
|
291
|
+
> .q-field__inner
|
|
292
|
+
> .q-field__control::after {
|
|
293
|
+
display: none !important;
|
|
294
|
+
}
|
|
295
|
+
</style>
|
package/src/ui/md3/Md3Layout.vue
CHANGED
|
@@ -1,71 +1,69 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<q-layout view="lHh Lpr lFf">
|
|
3
|
-
<
|
|
4
|
-
<q-
|
|
5
|
-
<q-
|
|
2
|
+
<q-layout v-if="ready" view="lHh Lpr lFf">
|
|
3
|
+
<q-header>
|
|
4
|
+
<q-toolbar>
|
|
5
|
+
<q-btn
|
|
6
|
+
v-if="!miniState"
|
|
7
|
+
flat
|
|
8
|
+
dense
|
|
9
|
+
round
|
|
10
|
+
aria-label="Menu"
|
|
11
|
+
icon="i-mdi-menu"
|
|
12
|
+
@click="toggleLeftDrawer()"
|
|
13
|
+
>
|
|
14
|
+
</q-btn>
|
|
15
|
+
<slot name="header-toolbar" />
|
|
16
|
+
</q-toolbar>
|
|
17
|
+
</q-header>
|
|
18
|
+
|
|
19
|
+
<q-drawer
|
|
20
|
+
ref="drawerRef"
|
|
21
|
+
:model-value="leftDrawerOpen"
|
|
22
|
+
:width="drawerWidth"
|
|
23
|
+
:mini-width="80"
|
|
24
|
+
:mini="miniState"
|
|
25
|
+
show-if-above
|
|
26
|
+
bordered
|
|
27
|
+
@hide="onDrawerHide"
|
|
28
|
+
@update:model-value="toggleLeftDrawer"
|
|
29
|
+
@mouseleave="debouncedToggleMiniState(true)"
|
|
30
|
+
>
|
|
31
|
+
<template #mini>
|
|
32
|
+
<div
|
|
33
|
+
:class="{
|
|
34
|
+
column: true,
|
|
35
|
+
'items-center': miniState,
|
|
36
|
+
'pr-0': true
|
|
37
|
+
}"
|
|
38
|
+
>
|
|
6
39
|
<q-btn
|
|
7
|
-
v-if="!miniState"
|
|
8
40
|
flat
|
|
9
41
|
dense
|
|
10
42
|
round
|
|
11
43
|
aria-label="Menu"
|
|
12
44
|
icon="i-mdi-menu"
|
|
45
|
+
class="q-mb-md"
|
|
13
46
|
@click="toggleLeftDrawer()"
|
|
14
47
|
>
|
|
15
48
|
</q-btn>
|
|
16
|
-
<
|
|
17
|
-
|
|
18
|
-
</q-header>
|
|
19
|
-
|
|
20
|
-
<q-drawer
|
|
21
|
-
ref="drawerRef"
|
|
22
|
-
:model-value="leftDrawerOpen"
|
|
23
|
-
:width="drawerWidth"
|
|
24
|
-
:mini-width="80"
|
|
25
|
-
:mini="miniState"
|
|
26
|
-
show-if-above
|
|
27
|
-
bordered
|
|
28
|
-
@hide="onDrawerHide"
|
|
29
|
-
@update:model-value="toggleLeftDrawer"
|
|
30
|
-
@mouseleave="debouncedToggleMiniState(true)"
|
|
31
|
-
>
|
|
32
|
-
<template #mini>
|
|
33
|
-
<div
|
|
34
|
-
:class="{
|
|
35
|
-
column: true,
|
|
36
|
-
'items-center': miniState,
|
|
37
|
-
'pr-0': true
|
|
38
|
-
}"
|
|
39
|
-
>
|
|
40
|
-
<q-btn
|
|
41
|
-
flat
|
|
42
|
-
dense
|
|
43
|
-
round
|
|
44
|
-
aria-label="Menu"
|
|
45
|
-
icon="i-mdi-menu"
|
|
46
|
-
class="q-mb-md"
|
|
47
|
-
@click="toggleLeftDrawer()"
|
|
48
|
-
>
|
|
49
|
-
</q-btn>
|
|
50
|
-
<div id="fabs" class="q-mb-md min-h-56px">
|
|
51
|
-
<slot name="fabs" :show-sticky="false" />
|
|
52
|
-
</div>
|
|
53
|
-
|
|
54
|
-
<slot name="drawer-mini-navigation" />
|
|
49
|
+
<div id="fabs" class="q-mb-md min-h-56px">
|
|
50
|
+
<slot name="fabs" :show-sticky="false" />
|
|
55
51
|
</div>
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
<
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
<
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
52
|
+
|
|
53
|
+
<slot name="drawer-mini-navigation" />
|
|
54
|
+
</div>
|
|
55
|
+
</template>
|
|
56
|
+
<slot name="drawer" />
|
|
57
|
+
</q-drawer>
|
|
58
|
+
|
|
59
|
+
<q-footer class="h-80px lt-md">
|
|
60
|
+
<slot name="footer" />
|
|
61
|
+
</q-footer>
|
|
62
|
+
|
|
63
|
+
<q-page-container>
|
|
64
|
+
<router-view />
|
|
65
|
+
<slot name="fabs" :show-sticky="true" />
|
|
66
|
+
</q-page-container>
|
|
69
67
|
</q-layout>
|
|
70
68
|
</template>
|
|
71
69
|
|
|
@@ -7,7 +7,11 @@
|
|
|
7
7
|
'gt-sm': true,
|
|
8
8
|
animated: !!seekAttention,
|
|
9
9
|
'animated-tada': !!seekAttention,
|
|
10
|
-
'animated-infinite': !!seekAttention
|
|
10
|
+
'animated-infinite': !!seekAttention,
|
|
11
|
+
'!bg-$light-primary-container': true,
|
|
12
|
+
'dark:!bg-$dark-primary-container': true,
|
|
13
|
+
'text-$on-light-primary-container': true,
|
|
14
|
+
'dark:text-$on-dark-primary-container': true
|
|
11
15
|
}"
|
|
12
16
|
fab
|
|
13
17
|
:icon="addIcon"
|
|
@@ -21,7 +25,11 @@
|
|
|
21
25
|
'gt-sm': true,
|
|
22
26
|
animated: !!seekAttention,
|
|
23
27
|
'animated-tada': !!seekAttention,
|
|
24
|
-
'animated-infinite': !!seekAttention
|
|
28
|
+
'animated-infinite': !!seekAttention,
|
|
29
|
+
'!bg-$light-primary-container': true,
|
|
30
|
+
'dark:!bg-$dark-primary-container': true,
|
|
31
|
+
'text-$on-light-primary-container': true,
|
|
32
|
+
'dark:text-$on-dark-primary-container': true
|
|
25
33
|
}"
|
|
26
34
|
fab
|
|
27
35
|
:icon="editIcon"
|