nuxt-hs-ui 1.0.10 → 2.0.2

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.
Files changed (112) hide show
  1. package/README.md +11 -4
  2. package/dist/module.d.mts +10 -2
  3. package/dist/module.d.ts +10 -2
  4. package/dist/module.json +5 -2
  5. package/dist/module.mjs +90 -51
  6. package/dist/runtime/assets/flatpickr-dark.css +1 -0
  7. package/dist/runtime/assets/flatpickr-month-select-style.css +1 -0
  8. package/dist/runtime/assets/tabulator-custom.css +1 -0
  9. package/dist/runtime/assets/tabulator.css +1 -0
  10. package/dist/runtime/assets/vue-select.css +1 -0
  11. package/dist/runtime/components/{hs-fc/btn/line-loading.vue → form/btn-line-loading.vue} +28 -42
  12. package/dist/runtime/components/form/btn.vue +488 -0
  13. package/dist/runtime/components/form/check-box.vue +352 -0
  14. package/dist/runtime/components/form/check-list.vue +354 -0
  15. package/dist/runtime/components/form/datepicker copy.vue +770 -0
  16. package/dist/runtime/components/form/datepicker.vue +897 -0
  17. package/dist/runtime/components/form/input-frame.vue +272 -0
  18. package/dist/runtime/components/form/radio.vue +685 -0
  19. package/dist/runtime/components/form/select-img-icon.vue +53 -0
  20. package/dist/runtime/components/form/select.vue +438 -0
  21. package/dist/runtime/components/form/text-box.vue +375 -0
  22. package/dist/runtime/components/form/textarea.vue +466 -0
  23. package/dist/runtime/components/form/value-box.vue +681 -0
  24. package/dist/runtime/components/interactive/alert.vue +113 -0
  25. package/dist/runtime/components/{hs-ui → interactive}/block-loading.vue +42 -59
  26. package/dist/runtime/components/{hs-ui/dialog/index.vue → interactive/dialog.vue} +132 -127
  27. package/dist/runtime/components/interactive/modal-bg.vue +82 -0
  28. package/dist/runtime/components/interactive/modal.vue +143 -0
  29. package/dist/runtime/components/{hs-ui/toast/index.vue → interactive/toast.vue} +76 -109
  30. package/dist/runtime/components/{hs-ui → interactive}/window-loader.vue +12 -9
  31. package/dist/runtime/components/{hs-ui → layout}/accordion.vue +21 -30
  32. package/dist/runtime/components/layout/aspect-box.vue +71 -0
  33. package/dist/runtime/components/layout/card-item.vue +193 -0
  34. package/dist/runtime/components/layout/card.vue +42 -0
  35. package/dist/runtime/components/layout/container.vue +40 -0
  36. package/dist/runtime/components/misc/breadcrumb.vue +96 -0
  37. package/dist/runtime/components/misc/tabulator.vue +187 -0
  38. package/dist/runtime/components/misc/view-name-display-target.vue +39 -0
  39. package/dist/runtime/components/misc/view-name-display.vue +90 -0
  40. package/dist/runtime/composables/use-hs-dialog.d.ts +40 -0
  41. package/dist/runtime/composables/{use-hs-ui-dialog.js → use-hs-dialog.js} +15 -10
  42. package/dist/runtime/composables/{use-hs-form-focus.d.ts → use-hs-focus.d.ts} +1 -1
  43. package/dist/runtime/composables/{use-hs-form-focus.js → use-hs-focus.js} +2 -4
  44. package/dist/runtime/composables/use-hs-misc.d.ts +22 -0
  45. package/dist/runtime/composables/use-hs-misc.js +62 -0
  46. package/dist/runtime/composables/use-hs-modal.d.ts +31 -0
  47. package/dist/runtime/{components/hs-ui/modal/use-ui-modal.js → composables/use-hs-modal.js} +18 -16
  48. package/dist/runtime/composables/use-hs-multi-lang.d.ts +14 -6
  49. package/dist/runtime/composables/use-hs-multi-lang.js +44 -11
  50. package/dist/runtime/composables/{use-hs-ui-toast.d.ts → use-hs-toast.d.ts} +3 -3
  51. package/dist/runtime/composables/{use-hs-ui-toast.js → use-hs-toast.js} +4 -5
  52. package/dist/runtime/composables/{use-hs-ui-window-loader.d.ts → use-hs-window-loader.d.ts} +1 -1
  53. package/dist/runtime/composables/{use-hs-ui-window-loader.js → use-hs-window-loader.js} +1 -2
  54. package/dist/runtime/plugin/v-select.d.ts +2 -0
  55. package/dist/runtime/plugin/v-select.js +5 -0
  56. package/dist/runtime/style.css +22 -1
  57. package/dist/runtime/tailwind.css +78 -0
  58. package/dist/runtime/types/app.config.d.ts +5 -0
  59. package/dist/runtime/{components/hs-ui/dialog/index.type.d.ts → types/dialog.d.ts} +3 -3
  60. package/dist/runtime/{components/hs-ui/toast/index.type.d.ts → types/toast.d.ts} +1 -2
  61. package/dist/runtime/{components/hs-ui/toast/index.type.js → types/toast.js} +0 -1
  62. package/dist/runtime/utils/class-style.d.ts +6 -0
  63. package/dist/runtime/utils/class-style.js +27 -0
  64. package/dist/runtime/utils/com.d.ts +6 -0
  65. package/dist/runtime/{lib → utils}/com.js +1 -4
  66. package/dist/runtime/utils/dayjs.d.ts +53 -0
  67. package/dist/runtime/utils/dayjs.js +124 -0
  68. package/dist/runtime/utils/float.d.ts +2 -0
  69. package/dist/runtime/utils/float.js +35 -0
  70. package/dist/runtime/utils/multi-lang-object.d.ts +17 -0
  71. package/dist/runtime/utils/multi-lang-object.js +34 -0
  72. package/dist/runtime/{lib → utils}/multi-lang.d.ts +1 -1
  73. package/dist/runtime/{lib → utils}/multi-lang.js +31 -27
  74. package/dist/runtime/{lib → utils}/number.d.ts +2 -4
  75. package/dist/runtime/{lib → utils}/number.js +29 -69
  76. package/dist/runtime/utils/object.d.ts +46 -0
  77. package/dist/runtime/utils/object.js +107 -0
  78. package/dist/runtime/utils/select-item.d.ts +31 -0
  79. package/dist/runtime/utils/select.d.ts +14 -0
  80. package/dist/runtime/utils/select.js +36 -0
  81. package/dist/runtime/utils/string.d.ts +39 -0
  82. package/dist/runtime/utils/string.js +125 -0
  83. package/dist/runtime/utils/tabulator.d.ts +108 -0
  84. package/dist/runtime/utils/tabulator.js +296 -0
  85. package/dist/runtime/utils/theme.d.ts +21 -0
  86. package/dist/runtime/utils/theme.js +31 -0
  87. package/dist/runtime/utils/tv.d.ts +101 -0
  88. package/dist/runtime/utils/tv.js +26 -0
  89. package/dist/runtime/utils/wareki.d.ts +3 -0
  90. package/dist/runtime/utils/wareki.js +106 -0
  91. package/dist/types.d.mts +1 -17
  92. package/dist/types.d.ts +1 -17
  93. package/package.json +99 -37
  94. package/dist/runtime/components/hs-fc/btn/index.vue +0 -510
  95. package/dist/runtime/components/hs-ui/aspect-box.vue +0 -83
  96. package/dist/runtime/components/hs-ui/card-item.vue +0 -141
  97. package/dist/runtime/components/hs-ui/card.vue +0 -54
  98. package/dist/runtime/components/hs-ui/container.vue +0 -50
  99. package/dist/runtime/components/hs-ui/modal/bg.vue +0 -94
  100. package/dist/runtime/components/hs-ui/modal/index.vue +0 -206
  101. package/dist/runtime/components/hs-ui/modal/use-ui-modal.d.ts +0 -20
  102. package/dist/runtime/components/v-test.vue +0 -60
  103. package/dist/runtime/composables/use-hs-ui-dialog.d.ts +0 -22
  104. package/dist/runtime/lib/class-style.d.ts +0 -8
  105. package/dist/runtime/lib/class-style.js +0 -59
  106. package/dist/runtime/lib/com.d.ts +0 -14
  107. package/dist/runtime/lib/prefix.d.ts +0 -2
  108. package/dist/runtime/lib/prefix.js +0 -17
  109. package/dist/runtime/lib/theme.d.ts +0 -2
  110. package/dist/runtime/lib/theme.js +0 -21
  111. /package/dist/runtime/{components/hs-ui/dialog/index.type.js → types/dialog.js} +0 -0
  112. /package/dist/runtime/{components/hs-fc/hoge → utils/select-item.js} +0 -0
@@ -0,0 +1,897 @@
1
+ <script setup lang="ts">
2
+ /* ----------------------------------------------------------------------------
3
+ // src\runtime\components\form\datepicker.vue
4
+ // ----------------------------------------------------------------------------
5
+ // Datepicker
6
+ // DatepickerDatepicker
7
+ ----------------------------------------------------------------------------- */
8
+
9
+ // [ node-modules ]
10
+ import dayjs from "dayjs";
11
+ import flatpickr from "flatpickr";
12
+ import monthSelectPlugin from "flatpickr/dist/plugins/monthSelect";
13
+ import { Japanese as ja } from "flatpickr/dist/l10n/ja";
14
+ import { english as en } from "flatpickr/dist/l10n/default";
15
+ // [ vueuse ]
16
+ import { useMounted } from "@vueuse/core";
17
+ // [ NUXT ]
18
+ import {
19
+ reactive,
20
+ ref,
21
+ watch,
22
+ computed,
23
+ useId,
24
+ onMounted,
25
+ nextTick,
26
+ onUnmounted,
27
+ } from "#imports";
28
+ // [ utils ]
29
+ import type { ClassType } from "../../utils/class-style";
30
+ import { GetTimeShiftValue, Dayjs, DayjsInit } from "../../utils/dayjs";
31
+ // [ composables ]
32
+ import { useHsMisc } from "../../composables/use-hs-misc";
33
+ import { useHsFocus } from "../../composables/use-hs-focus";
34
+ import { useHsToast } from "../../composables/use-hs-toast";
35
+ import { useHsMultiLang } from "../../composables/use-hs-multi-lang";
36
+ // [ Components ]
37
+ import InputFrame from "./input-frame.vue";
38
+
39
+ // ----------------------------------------------------------------------------
40
+ // [ nac-stroe ]
41
+ DayjsInit();
42
+ const hsFocus = useHsFocus();
43
+ const Toast = useHsToast();
44
+ const multiLang = useHsMultiLang();
45
+ const hsMisc = useHsMisc();
46
+ // ----------------------------------------------------------------------------
47
+ // [ vueuse ]
48
+ const isMounted = useMounted();
49
+ // ----------------------------------------------------------------------------
50
+ // flatpickr
51
+ const MonthSelectPlugin: any = monthSelectPlugin;
52
+ const timeDateFormat = "YYYY-MM-DD HH:mm:ss.SSS";
53
+ const timeOutputDateFormat = "HH:mm:ss.SSS";
54
+ const timeShowDateFormat = "HH:mm";
55
+ // ----------------------------------------------------------------------------
56
+ // [ Props ]
57
+ type Props = {
58
+ // ----------------------------------------------------------------------------
59
+ // Input 種類別
60
+ textAlign?: "left" | "center" | "right";
61
+ mode?: "all" | "date" | "time" | "month";
62
+ /** mode=time の場合、[HH:mm:ss.SSS] に固定 */
63
+ dataFormat?: string;
64
+ /** mode=time の場合、[HH:mm] に固定 */
65
+ showFormat?: string;
66
+ minDate?: string | null;
67
+ maxDate?: string | null;
68
+ hideDeleteBtn?: boolean;
69
+ hideTodayBtn?: boolean;
70
+ disableMobile?: boolean;
71
+ hasShift?: boolean;
72
+ // ----------------------------------------------------------------------------
73
+ data: string | null;
74
+ diff?: string | null | undefined;
75
+ tabindex?: string | undefined;
76
+ // ----------------------------------------------------------------------------
77
+ class?: ClassType;
78
+ classHeader?: ClassType;
79
+ classInput?: ClassType;
80
+ // ----------------------------------------------------------------------------
81
+ // 状態
82
+ focusColor?: string;
83
+ changeColor?: string;
84
+ error?: boolean;
85
+ errorColor?: string;
86
+ disabled?: boolean;
87
+ disabledColor?: string;
88
+ readonly?: boolean;
89
+ // ----------------------------------------------------------------------------
90
+ // 表示
91
+ label?: string;
92
+ // 表示-副情報
93
+ require?: boolean;
94
+ requireText?: string;
95
+ warn?: string;
96
+ warnTimeOut?: number;
97
+ // ----------------------------------------------------------------------------
98
+ // 設定
99
+ size?: "s" | "m" | "l";
100
+ // ----------------------------------------------------------------------------
101
+ uiText?: {
102
+ error: {
103
+ inputRangeTitle: string;
104
+ inputRangeMessage: string;
105
+ };
106
+ };
107
+ };
108
+
109
+ const props = withDefaults(defineProps<Props>(), {
110
+ // ----------------------------------------------------------------------------
111
+ // Input 種類別
112
+ textAlign: "left",
113
+ mode: "date",
114
+ dataFormat: "",
115
+ showFormat: "",
116
+ minDate: null,
117
+ maxDate: null,
118
+ hideDeleteBtn: false,
119
+ disableMobile: false,
120
+ hasShift: true,
121
+ // ----------------------------------------------------------------------------
122
+ diff: undefined,
123
+ tabindex: undefined,
124
+ // ----------------------------------------------------------------------------
125
+ class: "",
126
+ classHeader: "",
127
+ classInput: "",
128
+ // ----------------------------------------------------------------------------
129
+ // 状態
130
+ // focus: false,
131
+ focusColor: "shadow-[inset_0px_0px_1px_2px_#0d8ee4]",
132
+ // change: false,
133
+ changeColor: "shadow-[inset_0px_0px_1px_2px_#fd9831be]",
134
+ error: false,
135
+ errorColor: "shadow-[inset_0px_0px_1px_2px_#d80000dc]",
136
+ disabled: false,
137
+ disabledColor: "",
138
+ readonly: false,
139
+ // ----------------------------------------------------------------------------
140
+ // 表示
141
+ label: "",
142
+ // 表示-副情報
143
+ require: false,
144
+ requireText: "必須",
145
+ warn: "",
146
+ warnTimeOut: 300,
147
+ // ----------------------------------------------------------------------------
148
+ // 設定
149
+ size: "m",
150
+ // ----------------------------------------------------------------------------
151
+ uiText: () => {
152
+ return {
153
+ error: {
154
+ inputRangeTitle: "入力値エラー",
155
+ inputRangeMessage: "入力範囲外です",
156
+ },
157
+ };
158
+ },
159
+ });
160
+ // [ emit ]
161
+ type Emits = {
162
+ ref: [element: HTMLElement];
163
+ focus: [elm: HTMLElement];
164
+ blur: [elm: HTMLElement];
165
+ // ----------------------------
166
+ "update:data": [value: string | null];
167
+ "value-change": [after: string | null, before: string | null];
168
+ // ----------------------------
169
+ "reset-piceker-func": [func: any];
170
+ // ----------------------------
171
+ };
172
+ const emit = defineEmits<Emits>();
173
+ // ----------------------------------------------------------------------------
174
+ // ----------------------------------------------------------------------------
175
+ // [ getCurrentInstance ]
176
+ const uid = useId();
177
+
178
+ // ----------------------------------------------------------------------------
179
+ // [ reactive ]
180
+
181
+ interface State {
182
+ picker: any;
183
+ // FormControl値
184
+ date: Date | null;
185
+ // text: string;
186
+ option: any;
187
+ }
188
+ const state = reactive<State>({
189
+ // text: '',
190
+ picker: null,
191
+ date: null,
192
+ option: {
193
+ dateFormat: "Z",
194
+ locale: ja,
195
+ time_24hr: true,
196
+ minDate: undefined,
197
+ maxDate: undefined,
198
+ plugins: [],
199
+ disableMobile: true,
200
+ },
201
+ });
202
+
203
+ onMounted(() => {
204
+ state.option.maxDate =
205
+ dayjs(props.maxDate).isValid() === true
206
+ ? dayjs(props.maxDate).toISOString()
207
+ : undefined;
208
+ state.option.minDate =
209
+ dayjs(props.minDate).isValid() === true
210
+ ? dayjs(props.minDate).toISOString()
211
+ : undefined;
212
+ });
213
+ const shiftM = GetTimeShiftValue(Dayjs());
214
+ const getShiftDayjs = (date: any) => {
215
+ if (props.hasShift && shiftM !== 0) {
216
+ return dayjs(date).subtract(shiftM, "minute");
217
+ }
218
+ return dayjs(date);
219
+ };
220
+
221
+ const inputBoxClass = computed(() => {
222
+ if (props.textAlign === "left") {
223
+ return "display-left";
224
+ } else if (props.textAlign === "center") {
225
+ return "display-center";
226
+ } else {
227
+ return "display-right";
228
+ }
229
+ });
230
+ const displayText = computed(() => {
231
+ const lang = multiLang.state.lang;
232
+ dayjs.locale(lang);
233
+ if (props.data === null) {
234
+ return "";
235
+ } else if (props.mode === "time") {
236
+ return getShiftDayjs(dayjs().format("YYYY-MM-DD ") + props.data).format(
237
+ timeShowDateFormat
238
+ );
239
+ } else {
240
+ return getShiftDayjs(props.data).format(props.showFormat);
241
+ }
242
+ });
243
+
244
+ // ----------------------------------------------------------------------------
245
+ watch(
246
+ () =>
247
+ computed(() => {
248
+ return [props.minDate, props.maxDate, multiLang.state.lang];
249
+ }).value,
250
+ () => {
251
+ // console.log('computed', props.minDate, props.maxDate, isMounted.value);
252
+ if (!isMounted.value) return;
253
+ setTimeout(() => {
254
+ resetPicekr();
255
+ }, 1);
256
+ }
257
+ );
258
+
259
+ const checkDate = (date: any) => {
260
+ // console.log(props.minDate);
261
+ const d = getShiftDayjs(date);
262
+ if (props.minDate !== "" && d.isBefore(props.minDate)) {
263
+ // console.log('最小日付を下回っています', props.data, props.minDate);
264
+ return false;
265
+ } else if (props.maxDate !== "" && d.isAfter(props.maxDate)) {
266
+ // console.log('最大日付を下回っています', props.data, props.maxDate);
267
+ return false;
268
+ }
269
+ return true;
270
+ };
271
+
272
+ const keyDown = (event: any) => {
273
+ const before = props.data;
274
+ // console.log('keyDown', state.picker);
275
+ if (event.key === "Enter") {
276
+ datePickerToday();
277
+ return;
278
+ }
279
+ if (event.key === "Backspace") {
280
+ iconEventDelete();
281
+ return;
282
+ }
283
+ let move = 0;
284
+ if (event.key === "ArrowLeft" || event.key === "ArrowUp") {
285
+ move--;
286
+ }
287
+ if (event.key === "ArrowRight" || event.key === "ArrowDown") {
288
+ move++;
289
+ }
290
+ if (event.key === "ArrowUp" || event.key === "ArrowDown") {
291
+ // Flatpickerにフォーカスを奪われるキーイベントはフォーカスを取り戻す予約
292
+ setTimeout(() => {
293
+ // console.log('フォーカス戻す');
294
+ if (inputElement.value != null) {
295
+ inputElement.value.focus();
296
+ }
297
+ }, 150);
298
+ }
299
+ if (move !== 0) {
300
+ let m =
301
+ props.data == null ? getShiftDayjs(dayjs()) : getShiftDayjs(props.data);
302
+ if (move < 0) {
303
+ m = m.subtract(1, "d");
304
+ } else {
305
+ m = m.add(1, "d");
306
+ }
307
+ if (props.data !== "") {
308
+ if (checkDate(m) === false) {
309
+ // console.log('行き過ぎ');
310
+ return false;
311
+ }
312
+ } else if (move < 0) {
313
+ m = getShiftDayjs(props.maxDate).subtract(1, "d");
314
+ } else {
315
+ m = getShiftDayjs(props.minDate).add(1, "d");
316
+ }
317
+ emit("update:data", m.format(props.dataFormat));
318
+ nextTick(() => {
319
+ emit("value-change", m.format(props.dataFormat), before);
320
+ });
321
+ return false;
322
+ }
323
+ };
324
+
325
+ // ----------------------------------------------------------------------------
326
+ // [ flatpicker関連 ]
327
+ const initFlatPickerOption = () => {
328
+ if (props.mode === "all" || props.mode === "time") {
329
+ state.option.enableTime = true;
330
+ if (props.mode === "time") {
331
+ state.option.noCalendar = true;
332
+ }
333
+ }
334
+ if (props.mode === "month") {
335
+ state.option.disableMobile = true;
336
+ }
337
+ if (props.disableMobile) {
338
+ state.option.disableMobile = true;
339
+ }
340
+ if (props.mode === "month") {
341
+ state.option.plugins = [
342
+ new MonthSelectPlugin({
343
+ shorthand: true, // デフォルトはfalse
344
+ dateFormat: "m.y", // デフォルトは"F Y"
345
+ altFormat: "F Y", // デフォルトは"F Y"
346
+ theme: "dark", // デフォルトは"light"
347
+ }),
348
+ ];
349
+ }
350
+ };
351
+
352
+ const onOpen = () => {
353
+ focusState.isOpenFlatpickr = true;
354
+ };
355
+
356
+ const onClose = () => {
357
+ focusState.isOpenFlatpickr = false;
358
+ focusState.isClosingFlatpickr = true;
359
+ setTimeout(() => {
360
+ focusState.isClosingFlatpickr = false;
361
+ }, 200);
362
+ };
363
+
364
+ const onChange = (selectedDates: any) => {
365
+ let value = null;
366
+ if (selectedDates.length === 0) {
367
+ value = null;
368
+ } else {
369
+ const d = selectedDates[0];
370
+ if (d == null) {
371
+ value = null;
372
+ } else {
373
+ value = d;
374
+ }
375
+ }
376
+ updateValue(value);
377
+ };
378
+
379
+ const generateFlatPickerOption = () => {
380
+ // console.log('generatePicker', elmInput.value);
381
+ if (inputElement.value != null) {
382
+ dayjs.locale(multiLang.state.lang);
383
+ switch (multiLang.state.lang) {
384
+ case "ja":
385
+ state.option.locale = ja;
386
+ break;
387
+ case "en":
388
+ state.option.locale = en;
389
+ break;
390
+ default:
391
+ state.option.locale = en;
392
+ break;
393
+ }
394
+ // state.option.position = 'above';
395
+ // state.option.static = true;
396
+ state.picker = flatpickr(inputElement.value, state.option);
397
+ state.picker.config.onChange.push(onChange);
398
+ state.picker.config.onOpen.push(onOpen);
399
+ state.picker.config.onClose.push(onClose);
400
+ setValue();
401
+ // MonthSelectPlugin();
402
+ }
403
+ };
404
+ const flag = ref(false);
405
+
406
+ const resetPicekr = () => {
407
+ if (flag.value) return;
408
+ try {
409
+ flag.value = true;
410
+ state.picker.destroy();
411
+ state.picker = false;
412
+ focusState.isOpenFlatpickr = false;
413
+ dayjs.locale(multiLang.state.lang);
414
+ if (props.minDate !== null) {
415
+ state.option.minDate =
416
+ dayjs(props.minDate).isValid() === true
417
+ ? dayjs(props.minDate).toISOString()
418
+ : undefined;
419
+ } else {
420
+ state.option.minDate = null;
421
+ }
422
+ if (props.maxDate !== null) {
423
+ state.option.maxDate =
424
+ dayjs(props.maxDate).isValid() === true
425
+ ? dayjs(props.maxDate).toISOString()
426
+ : undefined;
427
+ } else {
428
+ state.option.maxDate = null;
429
+ }
430
+ generateFlatPickerOption();
431
+ } catch (error) {
432
+ console.error("resetPicekr()", error);
433
+ } finally {
434
+ flag.value = false;
435
+ }
436
+ };
437
+ emit("reset-piceker-func", resetPicekr);
438
+ watch(
439
+ () => props.data,
440
+ () => {
441
+ setValue();
442
+ }
443
+ );
444
+
445
+ const setValue = () => {
446
+ // console.log('setValue');
447
+ try {
448
+ if (props.data == null) {
449
+ state.picker.setDate(null);
450
+ state.date = null;
451
+ return;
452
+ }
453
+ const date =
454
+ props.mode === "time"
455
+ ? dayjs().format("YYYY-MM-DD ") + props.data
456
+ : props.data;
457
+ const d = getShiftDayjs(date);
458
+ // console.log('setValue', date);
459
+ if (d.isValid() === true) {
460
+ if (checkDate(props.data) === true) {
461
+ state.date = d.toDate();
462
+ state.picker.setDate(state.date);
463
+ return;
464
+ }
465
+ }
466
+ throw new Error("変換失敗");
467
+ } catch (err) {
468
+ console.error(err);
469
+ state.picker.setDate(null);
470
+ state.date = null;
471
+ updateValue(null);
472
+ }
473
+ };
474
+
475
+ // アイコン系イベント
476
+ const datePickerToggle = () => {
477
+ if (props.readonly === true) return;
478
+ if (props.disabled === true) return;
479
+ if (state.picker === null) return;
480
+ if (focusState.isClosingFlatpickr) return;
481
+ hsFocus.state.id = uid;
482
+ state.picker.open();
483
+ };
484
+
485
+ const datePickerToday = () => {
486
+ if (props.readonly === true) return;
487
+ if (props.disabled === true) return;
488
+ if (state.date !== null) return;
489
+ let inputValue = dayjs();
490
+ if (props.mode === "month") {
491
+ inputValue = inputValue.startOf("month");
492
+ }
493
+ const d = getShiftDayjs(inputValue);
494
+ if (checkDate(d.format("YYYY-MM-DD")) === false) {
495
+ Toast.Warning(
496
+ props.uiText.error.inputRangeMessage,
497
+ props.uiText.error.inputRangeTitle,
498
+ props.warnTimeOut
499
+ );
500
+ return;
501
+ }
502
+ if (props.mode === "time") {
503
+ updateValue(inputValue.format(timeDateFormat));
504
+ } else {
505
+ updateValue(inputValue.format(props.dataFormat));
506
+ }
507
+ };
508
+
509
+ const updateValue = async (text: string | null) => {
510
+ // console.log('updateValue', text);
511
+ const before = props.data;
512
+ if (text === null || text.length === 0) {
513
+ emit("update:data", null);
514
+ await nextTick();
515
+ emit("value-change", null, before);
516
+ return;
517
+ }
518
+ if (props.mode === "all") {
519
+ emit("update:data", dayjs(text).format(props.dataFormat));
520
+ nextTick(() => {
521
+ emit("value-change", dayjs(text).format(props.dataFormat), before);
522
+ });
523
+ } else if (props.mode === "time") {
524
+ emit("update:data", dayjs(text).format(timeOutputDateFormat));
525
+ nextTick(() => {
526
+ emit("value-change", dayjs(text).format(timeOutputDateFormat), before);
527
+ });
528
+ } else {
529
+ // 時間情報を削除する
530
+ emit(
531
+ "update:data",
532
+ dayjs(dayjs(text).format("YYYY-MM-DD")).format(props.dataFormat)
533
+ );
534
+ nextTick(() => {
535
+ emit(
536
+ "value-change",
537
+ dayjs(dayjs(text).format("YYYY-MM-DD")).format(props.dataFormat),
538
+ before
539
+ );
540
+ });
541
+ }
542
+ };
543
+
544
+ const iconEventDelete = () => {
545
+ const before = props.data;
546
+ if (props.readonly === true) return;
547
+ if (props.disabled === true) return;
548
+ if (state.date != null) {
549
+ emit("update:data", null);
550
+ nextTick(() => {
551
+ emit("value-change", null, before);
552
+ });
553
+ }
554
+ };
555
+
556
+ // [ ref ]
557
+ const inputElement = ref();
558
+ onMounted(() => {
559
+ emit("ref", inputElement.value as HTMLInputElement);
560
+ });
561
+
562
+ const setRef = (elm: any) => {
563
+ inputElement.value = elm;
564
+ emit("ref", elm);
565
+ };
566
+
567
+ // [ focus, blur ]
568
+
569
+ interface FocusState {
570
+ isOpenFlatpickr: boolean;
571
+ isClosingFlatpickr: boolean;
572
+ manualInput: boolean;
573
+ openBtn: boolean;
574
+ }
575
+
576
+ const focusState = reactive<FocusState>({
577
+ isOpenFlatpickr: false,
578
+ isClosingFlatpickr: false,
579
+ manualInput: false,
580
+ openBtn: false,
581
+ });
582
+
583
+ /**
584
+ * コントロールのFocus判定
585
+ */
586
+ const computedActivate = computed(() => {
587
+ if (props.disabled === true) return false;
588
+ if (props.readonly === true) return false;
589
+ if (hsFocus.state.id !== uid) return false;
590
+ if (focusState.isOpenFlatpickr) return true;
591
+ if (focusState.manualInput) return true;
592
+ if (focusState.openBtn) return true;
593
+ return false;
594
+ });
595
+
596
+ /**
597
+ * focus, blur イベント
598
+ */
599
+ watch(computedActivate, (value) => {
600
+ if (value === true) {
601
+ // クリックでの遷移の場合に
602
+ // 一つ前のコントロールのblurイベントよりも早くfocusが発生しないようにする対策で10ミリ秒処理をずらす
603
+ setTimeout(() => {
604
+ emit("focus", inputElement.value);
605
+ }, 10);
606
+ } else {
607
+ emit("blur", inputElement.value);
608
+ }
609
+ });
610
+
611
+ onMounted(() => {
612
+ initFlatPickerOption();
613
+ generateFlatPickerOption();
614
+ });
615
+ onUnmounted(() => {
616
+ if (state.picker != null) {
617
+ state.picker.destroy();
618
+ state.picker = null;
619
+ }
620
+ });
621
+ const tabindex = computed(() => {
622
+ if (props.disabled === true) return -1;
623
+ return props.tabindex;
624
+ });
625
+
626
+ // 更新の有無判定
627
+ const isChangeData = computed(() => {
628
+ if (props.diff === undefined) return false;
629
+ if (props.diff === null && props.data === "") return false;
630
+ if (props.diff === "" && props.data === null) return false;
631
+ if (props.diff !== props.data) return true;
632
+ return false;
633
+ });
634
+
635
+ const openBtn = ref<HTMLElement | null>();
636
+ const manualElm = ref<HTMLInputElement | null>();
637
+ const manualData = ref("");
638
+ const manualInput = ref(false);
639
+ const manualInputClick = () => {
640
+ if (props.readonly) return;
641
+ if (props.disabled) return;
642
+ if (hsMisc.state.isMobile) {
643
+ datePickerToggle();
644
+ return;
645
+ }
646
+ manualInput.value = true;
647
+ manualElm.value?.focus();
648
+ };
649
+ const manualInputfocus = () => {
650
+ if (props.readonly) return;
651
+ if (props.disabled) return;
652
+ manualData.value = displayText.value;
653
+ focusState.openBtn = false;
654
+ setTimeout(() => {
655
+ manualElm.value?.select();
656
+ hsFocus.state.id = uid;
657
+ focusState.manualInput = true;
658
+ }, 1);
659
+ };
660
+ const manualInputBlur = () => {
661
+ if (props.readonly) return;
662
+ if (props.disabled) return;
663
+ try {
664
+ const data = manualData.value
665
+ .replace(/\//g, "-")
666
+ .replace(/-(\d)-/g, "-0$1-")
667
+ .replace(/-(\d)$/g, "-0$1");
668
+ const dataFormat = props.showFormat.replace(/\//g, "-");
669
+ const dt = dayjs(data, dataFormat);
670
+ // console.log('manualInputBlur', { data, dataFormat, dt });
671
+ if (dt.isValid() === false) {
672
+ updateValue(null);
673
+ return;
674
+ }
675
+ updateValue(dt.format(props.dataFormat));
676
+ // console.log('manualInputBlur', data);
677
+ } catch (err) {
678
+ console.error("manualInputBlur", err);
679
+ } finally {
680
+ manualData.value = "";
681
+ manualInput.value = false;
682
+ focusState.manualInput = false;
683
+ }
684
+ };
685
+
686
+ const openBtnClick = () => {
687
+ if (props.readonly) return;
688
+ if (props.disabled) return;
689
+ if (!hsMisc.state.isMobile) {
690
+ inputElement.value?.focus();
691
+ return;
692
+ }
693
+ hsFocus.state.id = uid;
694
+ datePickerToggle();
695
+ };
696
+
697
+ const openBtnFocus = () => {
698
+ if (props.readonly) return;
699
+ if (props.disabled) return;
700
+ hsFocus.state.id = uid;
701
+ focusState.openBtn = true;
702
+ };
703
+ const computedIsFocusOpenBtn = computed(() => {
704
+ if (props.disabled === true) return false;
705
+ if (props.readonly === true) return false;
706
+ if (hsFocus.state.id !== uid) return false;
707
+ if (focusState.isOpenFlatpickr) return true;
708
+ if (focusState.openBtn) return true;
709
+ return false;
710
+ });
711
+
712
+ // ---------------------------------------------------------------------------------
713
+ </script>
714
+
715
+ <template>
716
+ <InputFrame
717
+ :class="props.class"
718
+ :class-header="props.classHeader"
719
+ :class-input="[props.classInput]"
720
+ :focus="computedActivate"
721
+ :focus-color="props.focusColor"
722
+ :change="isChangeData"
723
+ :change-color="props.changeColor"
724
+ :error="props.error"
725
+ :error-color="props.errorColor"
726
+ :disabled="props.disabled"
727
+ :disabled-color="props.disabledColor"
728
+ :readonly="props.readonly"
729
+ :label="props.label"
730
+ :require="props.require"
731
+ :require-text="props.requireText"
732
+ :warn="props.warn"
733
+ :warn-time-out="props.warnTimeOut"
734
+ :size="props.size"
735
+ >
736
+ <template v-if="!props.readonly" #left-icons="{ disabled: iconDisabled }">
737
+ <button
738
+ ref="openBtn"
739
+ data-sep="right"
740
+ data-icon="calendar"
741
+ :tabindex="tabindex"
742
+ :disabled="iconDisabled"
743
+ :class="
744
+ !iconDisabled
745
+ ? 'cursor-pointer hover:bg-accent1/[0.1] active:bg-accent1/[0.2]'
746
+ : ''
747
+ "
748
+ @click.stop.prevent="openBtnClick()"
749
+ @focus="openBtnFocus"
750
+ @blur="focusState.openBtn = false"
751
+ >
752
+ <div
753
+ class="tw-absolute tw-inset-[2px] tw-border-main2 tw-border tw-pointer-events-none tw-transition-all tw-rounded-sm"
754
+ :class="computedIsFocusOpenBtn ? 'tw-opacity-100' : 'tw-opacity-0'"
755
+ ></div>
756
+ <i
757
+ :class="
758
+ props.mode === 'time'
759
+ ? 'fa-regular fa-clock'
760
+ : 'fa-solid fa-calendar-days'
761
+ "
762
+ ></i>
763
+ <!-- <div
764
+ class="absolute inset-[2px] border-main2 border pointer-events-none transition-all rounded-sm"
765
+ :class="computedIsFocusOpenBtn ? 'opacity-100' : 'opacity-0'"
766
+ ></div> -->
767
+ </button>
768
+ </template>
769
+ <div
770
+ class="nac-c-input-p"
771
+ :class="[
772
+ { disabled: props.disabled, readonly: props.readonly },
773
+ inputBoxClass,
774
+ ]"
775
+ @click="manualInputClick"
776
+ @dblclick="datePickerToggle()"
777
+ >
778
+ <!---->
779
+ <!-- -->
780
+ <input
781
+ :ref="(e) => setRef(e)"
782
+ type="text"
783
+ class="flatpickr-body"
784
+ :disabled="props.disabled"
785
+ tabindex="-1"
786
+ @keydown="keyDown"
787
+ />
788
+ <input
789
+ ref="manualElm"
790
+ v-model="manualData"
791
+ type="text"
792
+ class="absolute inset-0"
793
+ :class="[
794
+ manualInput
795
+ ? 'pointer-events-auto opacity-100'
796
+ : 'pointer-events-none opacity-0',
797
+ inputBoxClass,
798
+ ]"
799
+ :tabindex="-1"
800
+ @blur="manualInputBlur()"
801
+ @focus="manualInputfocus()"
802
+ />
803
+ <span
804
+ :class="
805
+ !manualInput
806
+ ? 'pointer-events-auto opacity-100'
807
+ : 'pointer-events-none opacity-0'
808
+ "
809
+ >{{ displayText }}</span
810
+ >
811
+ <span
812
+ v-if="props.data === null && !props.hideTodayBtn"
813
+ class="today"
814
+ :class="
815
+ !manualInput
816
+ ? 'pointer-events-auto opacity-100'
817
+ : 'pointer-events-none opacity-0'
818
+ "
819
+ @click.stop="datePickerToday()"
820
+ >
821
+ {{ props.mode === "month" ? "Now" : "Today" }}
822
+ </span>
823
+ </div>
824
+ <template
825
+ v-if="!props.hideDeleteBtn && !props.readonly"
826
+ #right-icons="{ disabled: iconDisabled }"
827
+ >
828
+ <div
829
+ :class="
830
+ !iconDisabled
831
+ ? 'text-error cursor-pointer hover:bg-error/[0.1] active:bg-error/[0.2]'
832
+ : ''
833
+ "
834
+ @click="iconEventDelete()"
835
+ >
836
+ <i class="fa-solid fa-delete-left"></i>
837
+ </div>
838
+ </template>
839
+ </InputFrame>
840
+ </template>
841
+
842
+ <style scoped>
843
+ .nac-c-input-p {
844
+ width: 100%;
845
+ height: 100%;
846
+ padding: 0 4px;
847
+ }
848
+ .nac-c-input-p:not(.readonly) {
849
+ cursor: pointer;
850
+ }
851
+ .nac-c-input-p .today {
852
+ margin: 0 0 0 4px;
853
+ border-radius: 4px;
854
+ border: solid 1px #f68708;
855
+ background-color: rgb(255, 246, 237);
856
+ color: #e26f2c;
857
+ font-size: 12px;
858
+ padding: 1px 4px;
859
+ }
860
+ .nac-c-input-p .flatpickr-body {
861
+ position: absolute;
862
+ opacity: 0 !important;
863
+ top: 0px;
864
+ height: 40px;
865
+ height: 100%;
866
+ width: 40px;
867
+ left: 0;
868
+ z-index: -1;
869
+ pointer-events: none;
870
+ }
871
+
872
+ :deep(.flatpickr-mobile) {
873
+ position: absolute;
874
+ opacity: 0;
875
+ }
876
+
877
+ .nac-c-input-p {
878
+ display: flex;
879
+ align-items: center;
880
+ }
881
+ .nac-c-input-p.display-left {
882
+ justify-content: flex-start;
883
+ }
884
+ .nac-c-input-p.display-center {
885
+ justify-content: center;
886
+ }
887
+ .nac-c-input-p.display-right {
888
+ justify-content: flex-end;
889
+ }
890
+
891
+ .disabled .nac-c-input-p {
892
+ cursor: default;
893
+ }
894
+ .disabled .nac-c-input-p .today {
895
+ display: none;
896
+ }
897
+ </style>