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,352 @@
1
+ <script setup lang="ts">
2
+ /* ----------------------------------------------------------------------------
3
+ // src\runtime\components\form\check-box.vue
4
+ // ----------------------------------------------------------------------------
5
+ // CheckBox
6
+ // CheckBoxCheckBox
7
+ ----------------------------------------------------------------------------- */
8
+
9
+ // [ tailwind ]
10
+ import { twMerge } from "tailwind-merge";
11
+ // [ NUXT ]
12
+ import { reactive, ref, watch, computed, useId, nextTick } from "#imports";
13
+ // [ utils ]
14
+ import { type ClassType, ClassTypeToString } from "../../utils/class-style";
15
+ // [ composables ]
16
+ import { useHsFocus } from "../../composables/use-hs-focus";
17
+ import { useHsToast } from "../../composables/use-hs-toast";
18
+ // [ Components ]
19
+ import SelectImgIcon from "./select-img-icon.vue";
20
+ // ----------------------------------------------------------------------------
21
+ const hsFocus = useHsFocus();
22
+ const Toast = useHsToast();
23
+ // ----------------------------------------------------------------------------
24
+ // [ Props ]
25
+ type Props = {
26
+ // ----------------------------------------------------------------------------
27
+ // Input 種類別
28
+ // imageObjectFit?: 'contain' | 'cover';
29
+ // imageBorder?: string;
30
+ image?: boolean;
31
+ imgUrl?: string | null;
32
+ classImg?: ClassType;
33
+ classImgTag?: ClassType;
34
+ classLabel?: ClassType;
35
+ // ----------------------------------------------------------------------------
36
+ data: boolean | null;
37
+ diff?: boolean | null | undefined;
38
+ tabindex?: string | undefined;
39
+ // ----------------------------------------------------------------------------
40
+ // 状態
41
+ disabled?: boolean;
42
+ // ----------------------------------------------------------------------------
43
+ // 表示
44
+ label?: string;
45
+ warn?: string;
46
+ warnTimeOut?: number;
47
+ // ----------------------------------------------------------------------------
48
+ // 設定
49
+ size?: "s" | "m" | "l";
50
+ // ----------------------------------------------------------------------------
51
+ uiText?: {
52
+ validError: {
53
+ title: string;
54
+ };
55
+ };
56
+ };
57
+
58
+ const props = withDefaults(defineProps<Props>(), {
59
+ // imageObjectFit: 'contain',
60
+ // imageBorder: 'border-gray'
61
+ image: false,
62
+ imgUrl: null,
63
+ classImg: "",
64
+ classImgTag: "",
65
+ classLabel: "",
66
+ // ----------------------------------------------------------------------------
67
+ // data
68
+ data: false,
69
+ diff: undefined,
70
+ tabindex: undefined,
71
+ // ----------------------------------------------------------------------------
72
+ // 状態
73
+ disabled: false,
74
+ // ----------------------------------------------------------------------------
75
+ // 表示
76
+ label: "",
77
+ warn: "",
78
+ warnTimeOut: 300,
79
+ // ----------------------------------------------------------------------------
80
+ // 設定
81
+ size: "m",
82
+ uiText: () => {
83
+ return {
84
+ validError: {
85
+ title: "入力値の警告",
86
+ },
87
+ };
88
+ },
89
+ });
90
+ // ----------------------------------------------------------------------------
91
+ // [ emit ]
92
+ type Emits = {
93
+ ref: [element: HTMLElement];
94
+ focus: [elm: HTMLElement];
95
+ blur: [elm: HTMLElement];
96
+ // ----------------------------
97
+ "update:data": [value: boolean];
98
+ "value-change": [after: boolean, before: boolean | null];
99
+ // ----------------------------
100
+ keydown: [event: KeyboardEvent];
101
+ keyup: [event: KeyboardEvent];
102
+ // ----------------------------
103
+ };
104
+ const emit = defineEmits<Emits>();
105
+ // ----------------------------------------------------------------------------
106
+ // [ getCurrentInstance ]
107
+ const uid = useId();
108
+ // ----------------------------------------------------------------------------
109
+ // [ ref ]
110
+ const inputElement = ref();
111
+
112
+ const setRef = (elm: any) => {
113
+ inputElement.value = elm;
114
+ emit("ref", elm);
115
+ };
116
+
117
+ const switchValue = () => {
118
+ const before = props.data as boolean | null;
119
+ if (props.disabled === true) return;
120
+
121
+ if (props.data === true) {
122
+ emit("update:data", false);
123
+ nextTick(() => {
124
+ emit("value-change", false, before);
125
+ });
126
+ } else {
127
+ emit("update:data", true);
128
+ nextTick(() => {
129
+ emit("value-change", true, before);
130
+ });
131
+ }
132
+ if (inputElement.value !== null) {
133
+ inputElement.value.focus();
134
+ }
135
+ };
136
+
137
+ /**
138
+ * 強制focus
139
+ */
140
+ const elmFocus = () => {
141
+ inputElement.value.focus();
142
+ };
143
+
144
+ // [ focus, blur ]
145
+ interface FocusState {
146
+ isActivate: boolean;
147
+ isMmousedown: boolean;
148
+ }
149
+
150
+ const focusState = reactive<FocusState>({
151
+ isActivate: false,
152
+ isMmousedown: false,
153
+ });
154
+
155
+ /**
156
+ * コントロールのFocus判定
157
+ */
158
+ const computedActivate = computed(() => {
159
+ // console.log(JSON.stringify(focusState));
160
+ if (props.disabled === true) return false;
161
+ if (hsFocus.state.id !== uid) return false;
162
+ if (focusState.isActivate) return true;
163
+ if (focusState.isMmousedown) return true;
164
+ return false;
165
+ });
166
+
167
+ /**
168
+ * focus, blur イベント
169
+ */
170
+ watch(computedActivate, (value) => {
171
+ if (value === true) {
172
+ // クリックでの遷移の場合に
173
+ // 一つ前のコントロールのblurイベントよりも早くfocusが発生しないようにする対策で10ミリ秒処理をずらす
174
+ setTimeout(() => {
175
+ emit("focus", inputElement.value);
176
+ }, 10);
177
+ } else {
178
+ emit("blur", inputElement.value);
179
+ }
180
+ });
181
+ const onMousedown = () => {
182
+ if (props.disabled === true) return;
183
+ focusState.isMmousedown = true;
184
+ };
185
+ const onMouseup = () => {
186
+ if (props.disabled === true) return;
187
+ elmFocus();
188
+ focusState.isMmousedown = false;
189
+ };
190
+ const onFocus = () => {
191
+ if (props.disabled === true) return;
192
+ focusState.isActivate = true;
193
+ hsFocus.state.id = uid;
194
+ };
195
+ const onBlur = () => {
196
+ focusState.isActivate = false;
197
+ };
198
+
199
+ // [ iconEventShowWarn ]
200
+ const iconEventShowWarn = () => {
201
+ Toast.Warning(props.warn, props.uiText.validError.title, props.warnTimeOut);
202
+ };
203
+ const tabindex = computed(() => {
204
+ if (props.disabled === true) return -1;
205
+ return props.tabindex;
206
+ });
207
+ //
208
+ // ----------------------------------------------------------------------------
209
+ // Class
210
+
211
+ const baseClass = computed(() => {
212
+ return {
213
+ disabled: props.disabled,
214
+ activate: computedActivate.value,
215
+ diff:
216
+ props.diff !== undefined &&
217
+ props.diff !== props.data &&
218
+ !(props.diff === null && props.data === true),
219
+ };
220
+ });
221
+
222
+ const boxClass = computed(() => {
223
+ return [
224
+ twMerge(
225
+ "border border-gray-700",
226
+ !props.disabled ? "cursor-pointer" : "cursor-not-allowed",
227
+ !props.disabled ? "bg-white" : "bg-gray-100",
228
+ props.size === "s" ? "w-[16px] h-[16px] " : "",
229
+ props.size === "m" ? "w-[18px] h-[18px] " : "",
230
+ props.size === "l" ? "w-[22px] h-[22px] " : ""
231
+ ),
232
+ ];
233
+ });
234
+
235
+ const checkClass = computed(() => {
236
+ return [
237
+ twMerge(
238
+ "absolute inset-0",
239
+ "flex items-center justify-center",
240
+ props.size === "s" ? "text-[14px]" : "",
241
+ props.size === "m" ? "text-[16px]" : "",
242
+ props.size === "l" ? "text-[18px]" : "",
243
+ props.data === true ? "scale-100" : "scale-0"
244
+ ),
245
+ ];
246
+ });
247
+ const labelClass = computed(() => {
248
+ return [
249
+ twMerge(
250
+ "flex items-center gap-[2px]",
251
+ !props.disabled ? "cursor-pointer" : "cursor-not-allowed",
252
+ props.size === "s" ? "text-[14px] ps-[6px]" : "",
253
+ props.size === "m" ? "text-[16px] ps-[8px]" : "",
254
+ props.size === "l" ? "text-[20px] ps-[10px]" : "",
255
+ ClassTypeToString(props.classLabel)
256
+ ),
257
+ ];
258
+ });
259
+
260
+ // ----------------------------------------------------------------------------
261
+ </script>
262
+
263
+ <template>
264
+ <div class="nac-checkbox" :class="baseClass">
265
+ <input
266
+ :ref="(e) => setRef(e)"
267
+ :tabindex="tabindex"
268
+ type="checkbox"
269
+ class="checkbox"
270
+ @blur="onBlur()"
271
+ @focus="onFocus()"
272
+ />
273
+ <div
274
+ class="nac-checkbox-box flex-none"
275
+ :class="[boxClass, { checked: props.data === true }]"
276
+ @click="switchValue()"
277
+ >
278
+ <div :class="checkClass">
279
+ <i class="fas fa-check text-green-600"></i>
280
+ </div>
281
+ </div>
282
+ <div
283
+ class="nac-checkbox-text"
284
+ :class="labelClass"
285
+ @mousedown="onMousedown()"
286
+ @mouseup="onMouseup()"
287
+ @click="switchValue()"
288
+ >
289
+ <SelectImgIcon
290
+ v-if="props.image"
291
+ class="flex-none"
292
+ :img-url="props.imgUrl"
293
+ :class-img="props.classImg"
294
+ :class-img-tag="props.classImgTag"
295
+ />
296
+ <div class="flex-1 min-w-[0] whitespace-pre-wrap break-words">
297
+ {{ label }}
298
+ <slot />
299
+ </div>
300
+ <span
301
+ v-if="props.warn.length !== 0"
302
+ class="warn flex-none"
303
+ @click.stop="iconEventShowWarn()"
304
+ >
305
+ <i class="fas fa-exclamation-triangle"></i>{{ props.warn }}
306
+ </span>
307
+ </div>
308
+ </div>
309
+ </template>
310
+
311
+ <style scoped>
312
+ .nac-checkbox {
313
+ display: inline-flex;
314
+ align-items: center;
315
+ }
316
+ .nac-checkbox > .checkbox {
317
+ z-index: -1;
318
+ position: absolute;
319
+ opacity: 0;
320
+ pointer-events: none;
321
+ }
322
+ .nac-checkbox .nac-checkbox-box > div {
323
+ transition: transform 100ms;
324
+ will-change: transform;
325
+ transform-origin: center center;
326
+ }
327
+ .nac-checkbox .nac-checkbox-text {
328
+ min-width: 0;
329
+ line-height: 1em;
330
+ }
331
+ .nac-checkbox .nac-checkbox-text .warn {
332
+ color: rgb(190, 0, 0);
333
+ }
334
+ .nac-checkbox.disabled {
335
+ cursor: default;
336
+ }
337
+ .nac-checkbox.disabled:not(.activate) .nac-checkbox-box {
338
+ box-shadow: inset 0px 0px 1px 2px #858585;
339
+ }
340
+ .nac-checkbox.disabled:not(.activate) .nac-checkbox-text {
341
+ opacity: 0.8;
342
+ }
343
+ .nac-checkbox.diff:not(.activate):not(.disabled) .nac-checkbox-box {
344
+ box-shadow: inset 0px 0px 1px 2px rgba(253, 152, 49, 0.7450980392);
345
+ }
346
+ .nac-checkbox.activate:not(.disabled) .nac-checkbox-box {
347
+ box-shadow: inset 0px 0px 1px 2px #0d8ee4;
348
+ }
349
+ .nac-checkbox.activate:not(.disabled) .nac-checkbox-text {
350
+ text-decoration: underline;
351
+ }
352
+ </style>
@@ -0,0 +1,354 @@
1
+ <script setup lang="ts">
2
+ /* ----------------------------------------------------------------------------
3
+ // src\runtime\components\form\check-list.vue
4
+ // ----------------------------------------------------------------------------
5
+ // CheckList
6
+ // CheckListCheckList
7
+ ----------------------------------------------------------------------------- */
8
+
9
+ // [ tailwind ]
10
+ import { twMerge } from "tailwind-merge";
11
+ // [ NUXT ]
12
+ import { reactive, ref, watch, computed, nextTick } from "#imports";
13
+ // [ utils ]
14
+ import { type ClassType, ClassTypeToString } from "../../utils/class-style";
15
+ import type { MultiLang } from "../../utils/multi-lang";
16
+ import { ObjectCompare, ListIdSort } from "../../utils/object";
17
+ import type { SelectItem } from "../../utils/select-item";
18
+ // [ composables ]
19
+ import { useHsMultiLang } from "../../composables/use-hs-multi-lang";
20
+ // [ Components ]
21
+ import InputFrame from "./input-frame.vue";
22
+ import HsFcCheckBox from "./check-box.vue";
23
+ // ----------------------------------------------------------------------------
24
+ // ----------------------------------------------------------------------------
25
+ const multiLang = useHsMultiLang();
26
+ const tx = multiLang.tx;
27
+ // ----------------------------------------------------------------------------
28
+ // [ Props ]
29
+ type Props = {
30
+ // ----------------------------------------------------------------------------
31
+ // Input 種類別
32
+ list: SelectItem[] | readonly SelectItem[];
33
+ image?: boolean;
34
+ nullText?: string;
35
+ classRow?: ClassType;
36
+ classCol?: ClassType;
37
+ classItem?: ClassType;
38
+ classImg?: ClassType;
39
+ classImgTag?: ClassType;
40
+ // ----------------------------------------------------------------------------
41
+ data: number[];
42
+ diff?: number[] | undefined;
43
+ tabindex?: string | undefined;
44
+ // ----------------------------------------------------------------------------
45
+ class?: ClassType;
46
+ classHeader?: ClassType;
47
+ classInput?: ClassType;
48
+ // ----------------------------------------------------------------------------
49
+ // 状態
50
+ focusColor?: string;
51
+ changeColor?: string;
52
+ error?: boolean;
53
+ errorColor?: string;
54
+ disabled?: boolean;
55
+ disabledColor?: string;
56
+ readonly?: boolean;
57
+ // ----------------------------------------------------------------------------
58
+ // 表示
59
+ label?: string;
60
+ // 表示-副情報
61
+ require?: boolean;
62
+ requireText?: string;
63
+ warn?: string;
64
+ warnTimeOut?: number;
65
+ // ----------------------------------------------------------------------------
66
+ // 設定
67
+ size?: "s" | "m" | "l";
68
+ // ----------------------------------------------------------------------------
69
+ };
70
+ const props = withDefaults(defineProps<Props>(), {
71
+ // ----------------------------------------------------------------------------
72
+ // Input 種類別
73
+ order: false,
74
+ image: false,
75
+ nullText: "選択してください",
76
+ nullable: true,
77
+ classRow: "",
78
+ classCol: "",
79
+ classItem: "",
80
+ classImg: "",
81
+ classImgTag: "",
82
+ // ----------------------------------------------------------------------------
83
+ diff: undefined,
84
+ tabindex: undefined,
85
+ // ----------------------------------------------------------------------------
86
+ class: "",
87
+ classHeader: "",
88
+ classInput: "",
89
+ // ----------------------------------------------------------------------------
90
+ // 状態
91
+ // focus: false,
92
+ focusColor: "shadow-[inset_0px_0px_1px_2px_#0d8ee4]",
93
+ // change: false,
94
+ changeColor: "shadow-[inset_0px_0px_1px_2px_#fd9831be]",
95
+ error: false,
96
+ errorColor: "shadow-[inset_0px_0px_1px_2px_#d80000dc]",
97
+ disabled: false,
98
+ disabledColor: "",
99
+ readonly: false,
100
+ // ----------------------------------------------------------------------------
101
+ // 表示
102
+ label: "",
103
+ // 表示-副情報
104
+ require: false,
105
+ requireText: "必須",
106
+ warn: "",
107
+ warnTimeOut: 300,
108
+ // ----------------------------------------------------------------------------
109
+ // 設定
110
+ size: "m",
111
+ });
112
+ // [ emit ]
113
+ type InputFocusEventArg = {
114
+ elm: HTMLElement;
115
+ label: MultiLang;
116
+ data: number[];
117
+ };
118
+ type Emits = {
119
+ ref: [element: HTMLElement];
120
+ focus: [arg: InputFocusEventArg];
121
+ blur: [arg: InputFocusEventArg];
122
+ "update:data": [value: number[], id: number];
123
+ "value-change": [after: number[], before: number[], id: number];
124
+ };
125
+ const emit = defineEmits<Emits>();
126
+
127
+ // ----------------------------------------------------------------------------
128
+
129
+ // [ 選択肢配列 ]
130
+ interface ItemListRow {
131
+ id: number;
132
+ text: MultiLang;
133
+ focus: boolean;
134
+ imgUrl: string | null;
135
+ }
136
+ const itemList = ref<ItemListRow[]>([]);
137
+ watch(
138
+ () => [...props.list],
139
+ () => {
140
+ //
141
+ setItemList();
142
+ }
143
+ );
144
+ const setItemList = () => {
145
+ itemList.value = props.list.map((row) => {
146
+ return {
147
+ id: row.id,
148
+ text: row.text,
149
+ imgUrl: row.imgUrl === undefined ? null : row.imgUrl,
150
+ focus: false,
151
+ } as ItemListRow;
152
+ });
153
+ };
154
+ setItemList();
155
+
156
+ // ----------------------------------------------------------------------------
157
+
158
+ const valueChange = async (id: number) => {
159
+ const before = props.data.map((row) => row);
160
+ let temp = props.data.map((row) => row);
161
+ if (props.data.includes(id)) {
162
+ // console.log('valueChange off', id);
163
+ temp = props.data.filter((row) => {
164
+ if (row === id) {
165
+ return false;
166
+ } else {
167
+ return true;
168
+ }
169
+ });
170
+ } else {
171
+ // console.log('valueChange on', id, value);
172
+ temp.push(id);
173
+ }
174
+ const ret = ListIdSort([...props.list], temp);
175
+ emit("update:data", ret, id);
176
+ await nextTick();
177
+ emit("value-change", ret, before, id);
178
+ };
179
+
180
+ // ----------------------------------------------------------------------------
181
+ // [ ref ]
182
+ const inputElement = ref();
183
+ const setRef = (elm: any, index: number) => {
184
+ if (index === 0) {
185
+ inputElement.value = elm;
186
+ emit("ref", inputElement.value as HTMLInputElement);
187
+ }
188
+ };
189
+
190
+ // [ focus, blur ]
191
+ interface FocusState {
192
+ isMmousedown: boolean;
193
+ }
194
+
195
+ const focusState = reactive<FocusState>({
196
+ isMmousedown: false,
197
+ });
198
+
199
+ /**
200
+ * コントロールのFocus判定
201
+ */
202
+ const computedActivate = computed(() => {
203
+ if (focusState.isMmousedown) return true;
204
+ if (itemList.value.filter((row) => row.focus === true).length !== 0)
205
+ return true;
206
+ return false;
207
+ });
208
+
209
+ /**
210
+ * focus, blur イベント
211
+ */
212
+ watch(computedActivate, (value) => {
213
+ if (value === true) {
214
+ // クリックでの遷移の場合に
215
+ // 一つ前のコントロールのblurイベントよりも早くfocusが発生しないようにする対策で10ミリ秒処理をずらす
216
+ setTimeout(() => {
217
+ emit("focus", {
218
+ elm: inputElement.value,
219
+ label: props.label,
220
+ data: props.data.map((row) => row),
221
+ });
222
+ }, 10);
223
+ } else {
224
+ emit("blur", {
225
+ elm: inputElement.value,
226
+ label: props.label,
227
+ data: props.data.map((row) => row),
228
+ });
229
+ }
230
+ });
231
+
232
+ const onFocus = (row: ItemListRow) => {
233
+ row.focus = true;
234
+ };
235
+
236
+ const onBlur = (row: ItemListRow) => {
237
+ setTimeout(() => {
238
+ row.focus = false;
239
+ }, 10);
240
+ };
241
+
242
+ // 更新の有無判定
243
+ const isChangeData = computed(() => {
244
+ if (props.diff === undefined) return false;
245
+ return !ObjectCompare(
246
+ props.diff.map((row) => row).sort(),
247
+ props.data.map((row) => row)
248
+ );
249
+ });
250
+
251
+ const tabindex = computed(() => {
252
+ if (props.disabled === true) return -1;
253
+ return props.tabindex;
254
+ });
255
+ // ----------------------------------------------------------------------------
256
+ // Class
257
+ const baseClass = computed(() => {
258
+ return [
259
+ twMerge(
260
+ //
261
+ "h-auto",
262
+ props.size === "s" ? "min-h-[44px] " : "",
263
+ props.size === "m" ? "min-h-[48px]" : "",
264
+ props.size === "l" ? "min-h-[60px]" : "",
265
+ ClassTypeToString(props.class)
266
+ ),
267
+ ];
268
+ });
269
+ const rowClass = computed(() => {
270
+ return twMerge(
271
+ //
272
+ "flex items-center flex-wrap",
273
+ ClassTypeToString(props.classRow)
274
+ );
275
+ });
276
+ const colClass = computed(() => {
277
+ return twMerge(
278
+ //
279
+ "min-w-[0]",
280
+ ClassTypeToString(props.classCol)
281
+ );
282
+ });
283
+
284
+ const itemClass = computed(() => {
285
+ return twMerge(
286
+ //
287
+ "px-[6px] py-[1px] w-full",
288
+ ClassTypeToString(props.classItem)
289
+ );
290
+ });
291
+
292
+ // ----------------------------------------------------------------------------
293
+ </script>
294
+
295
+ <template>
296
+ <InputFrame
297
+ :class="baseClass"
298
+ :class-header="props.classHeader"
299
+ :class-input="props.classInput"
300
+ :focus="computedActivate"
301
+ :focus-color="props.focusColor"
302
+ :change="isChangeData"
303
+ :change-color="props.changeColor"
304
+ :error="props.error"
305
+ :error-color="props.errorColor"
306
+ :disabled="props.disabled"
307
+ :disabled-color="props.disabledColor"
308
+ :readonly="props.readonly"
309
+ :label="props.label"
310
+ :require="props.require"
311
+ :require-text="props.requireText"
312
+ :warn="props.warn"
313
+ :warn-time-out="props.warnTimeOut"
314
+ :size="props.size"
315
+ >
316
+ <template v-if="$slots.overlay" #overlay>
317
+ <slot name="overlay"></slot>
318
+ </template>
319
+ <div class="nac-input-box" @mousedown.stop="" @mouseup.stop="">
320
+ <div
321
+ class="w-full h-full"
322
+ :class="rowClass"
323
+ style="background-color: transparent"
324
+ >
325
+ <template v-for="(row, index) in itemList" :key="index">
326
+ <div :class="colClass">
327
+ <HsFcCheckBox
328
+ :data="props.data.includes(row.id) === true"
329
+ :label="tx(row.text).value"
330
+ :class="itemClass"
331
+ :class-img="props.classImg"
332
+ :class-img-tag="props.classImgTag"
333
+ :image="props.image"
334
+ :img-url="row.imgUrl"
335
+ :tabindex="tabindex"
336
+ :disabled="props.disabled"
337
+ @value-change="(value) => valueChange(row.id)"
338
+ @focus="() => onFocus(row)"
339
+ @blur="() => onBlur(row)"
340
+ @ref="(e) => setRef(e, index)"
341
+ />
342
+ </div>
343
+ </template>
344
+ </div>
345
+ </div>
346
+ </InputFrame>
347
+ </template>
348
+
349
+ <style scoped>
350
+ .nac-input-box {
351
+ width: 100%;
352
+ height: 100%;
353
+ }
354
+ </style>