nuxt-hs-ui 2.12.6 → 4.0.0

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 (131) hide show
  1. package/README.md +202 -14
  2. package/dist/module.d.mts +3 -4
  3. package/dist/module.json +9 -6
  4. package/dist/module.mjs +109 -99
  5. package/dist/runtime/assets/flatpickr-dark.css +1 -1
  6. package/dist/runtime/assets/main.css +1 -0
  7. package/dist/runtime/assets/tabulator-custom.css +1 -1
  8. package/dist/runtime/components/form/_select/hidden-item-toggle.vue +28 -0
  9. package/dist/runtime/components/form/_select/hidden-item-toggle.vue.d.ts +10 -0
  10. package/dist/runtime/components/form/_select/item-container.vue +63 -0
  11. package/dist/runtime/components/form/_select/item-container.vue.d.ts +19 -0
  12. package/dist/runtime/components/form/_select/item-label.vue +31 -0
  13. package/dist/runtime/components/form/_select/item-label.vue.d.ts +13 -0
  14. package/dist/runtime/components/form/_select/item-row.vue +62 -0
  15. package/dist/runtime/components/form/_select/item-row.vue.d.ts +34 -0
  16. package/dist/runtime/components/form/btn-line-loading.vue +62 -81
  17. package/dist/runtime/components/form/btn-line-loading.vue.d.ts +14 -0
  18. package/dist/runtime/components/form/btn.vue +411 -494
  19. package/dist/runtime/components/form/btn.vue.d.ts +0 -0
  20. package/dist/runtime/components/form/check-box.vue +200 -315
  21. package/dist/runtime/components/form/check-box.vue.d.ts +71 -0
  22. package/dist/runtime/components/form/check-list.vue +234 -364
  23. package/dist/runtime/components/form/check-list.vue.d.ts +99 -0
  24. package/dist/runtime/components/form/combo-box.vue +340 -0
  25. package/dist/runtime/components/form/combo-box.vue.d.ts +69 -0
  26. package/dist/runtime/components/form/datepicker.vue +717 -883
  27. package/dist/runtime/components/form/datepicker.vue.d.ts +122 -0
  28. package/dist/runtime/components/form/input-frame.vue +174 -258
  29. package/dist/runtime/components/form/input-frame.vue.d.ts +88 -0
  30. package/dist/runtime/components/form/radio.vue +451 -614
  31. package/dist/runtime/components/form/radio.vue.d.ts +62 -0
  32. package/dist/runtime/components/form/select-img-icon.vue +38 -53
  33. package/dist/runtime/components/form/select-img-icon.vue.d.ts +15 -0
  34. package/dist/runtime/components/form/select.vue +733 -579
  35. package/dist/runtime/components/form/select.vue.d.ts +63 -0
  36. package/dist/runtime/components/form/text-box.vue +266 -365
  37. package/dist/runtime/components/form/text-box.vue.d.ts +105 -0
  38. package/dist/runtime/components/form/textarea.vue +338 -421
  39. package/dist/runtime/components/form/textarea.vue.d.ts +98 -0
  40. package/dist/runtime/components/form/value-box.vue +512 -641
  41. package/dist/runtime/components/form/value-box.vue.d.ts +128 -0
  42. package/dist/runtime/components/interactive/alert.vue +49 -113
  43. package/dist/runtime/components/interactive/alert.vue.d.ts +30 -0
  44. package/dist/runtime/components/interactive/block-loading.vue +91 -119
  45. package/dist/runtime/components/interactive/block-loading.vue.d.ts +22 -0
  46. package/dist/runtime/components/interactive/dialog.vue +252 -407
  47. package/dist/runtime/components/interactive/dialog.vue.d.ts +3 -0
  48. package/dist/runtime/components/interactive/modal-bg.vue +72 -82
  49. package/dist/runtime/components/interactive/modal-bg.vue.d.ts +11 -0
  50. package/dist/runtime/components/interactive/modal.vue +121 -169
  51. package/dist/runtime/components/interactive/modal.vue.d.ts +38 -0
  52. package/dist/runtime/components/interactive/toast.vue +164 -206
  53. package/dist/runtime/components/interactive/toast.vue.d.ts +3 -0
  54. package/dist/runtime/components/interactive/window-loader.vue +61 -84
  55. package/dist/runtime/components/interactive/window-loader.vue.d.ts +3 -0
  56. package/dist/runtime/components/layout/accordion-down.vue +72 -0
  57. package/dist/runtime/components/layout/accordion-down.vue.d.ts +26 -0
  58. package/dist/runtime/components/layout/accordion.vue +47 -78
  59. package/dist/runtime/components/layout/accordion.vue.d.ts +22 -0
  60. package/dist/runtime/components/layout/aspect-box.vue +29 -58
  61. package/dist/runtime/components/layout/aspect-box.vue.d.ts +29 -0
  62. package/dist/runtime/components/layout/card-item.vue +148 -193
  63. package/dist/runtime/components/layout/card-item.vue.d.ts +0 -0
  64. package/dist/runtime/components/layout/card.vue +27 -42
  65. package/dist/runtime/components/layout/card.vue.d.ts +23 -0
  66. package/dist/runtime/components/layout/container.vue +25 -40
  67. package/dist/runtime/components/layout/container.vue.d.ts +35 -0
  68. package/dist/runtime/components/layout/divider-h.vue +30 -50
  69. package/dist/runtime/components/layout/divider-h.vue.d.ts +18 -0
  70. package/dist/runtime/components/misc/breadcrumb.vue +47 -95
  71. package/dist/runtime/components/misc/breadcrumb.vue.d.ts +22 -0
  72. package/dist/runtime/components/misc/tabulator.vue +122 -190
  73. package/dist/runtime/components/misc/tabulator.vue.d.ts +28 -0
  74. package/dist/runtime/components/misc/view-name-display.vue +53 -68
  75. package/dist/runtime/components/misc/view-name-display.vue.d.ts +14 -0
  76. package/dist/runtime/components/test.vue +13 -0
  77. package/dist/runtime/components/test.vue.d.ts +3 -0
  78. package/dist/runtime/composables/test.d.ts +8 -0
  79. package/dist/runtime/composables/test.js +12 -0
  80. package/dist/runtime/composables/use-hs-dialog.d.ts +3 -20
  81. package/dist/runtime/composables/use-hs-dialog.js +3 -9
  82. package/dist/runtime/composables/use-hs-is-mobile.d.ts +8 -2
  83. package/dist/runtime/composables/use-hs-is-mobile.js +43 -26
  84. package/dist/runtime/composables/use-hs-misc.d.ts +8 -38
  85. package/dist/runtime/composables/use-hs-misc.js +9 -61
  86. package/dist/runtime/composables/use-hs-modal.js +1 -3
  87. package/dist/runtime/composables/use-hs-multi-lang.d.ts +23 -40
  88. package/dist/runtime/composables/use-hs-multi-lang.js +30 -74
  89. package/dist/runtime/composables/use-hs-scroll-lock.d.ts +1 -1
  90. package/dist/runtime/composables/use-hs-scroll-lock.js +2 -1
  91. package/dist/runtime/composables/use-hs-toast.d.ts +2 -2
  92. package/dist/runtime/composables/use-hs-toast.js +12 -4
  93. package/dist/runtime/composables/use-pinia.d.ts +1 -0
  94. package/dist/runtime/composables/use-pinia.js +2 -0
  95. package/dist/runtime/plugin.d.ts +2 -0
  96. package/dist/runtime/plugin.js +4 -0
  97. package/dist/runtime/server/tsconfig.json +3 -3
  98. package/dist/runtime/types/dialog.d.ts +11 -20
  99. package/dist/runtime/types/dialog.js +2 -1
  100. package/dist/runtime/types/flatpickr/default.js +2 -23
  101. package/dist/runtime/types/flatpickr/ja.js +3 -37
  102. package/dist/runtime/types/toast.d.ts +1 -1
  103. package/dist/runtime/utils/dayjs.d.ts +8 -6
  104. package/dist/runtime/utils/dayjs.js +12 -5
  105. package/dist/runtime/utils/modal.d.ts +9 -28
  106. package/dist/runtime/utils/modal.js +7 -36
  107. package/dist/runtime/utils/multi-lang-object.d.ts +2 -2
  108. package/dist/runtime/utils/multi-lang-object.js +1 -5
  109. package/dist/runtime/utils/multi-lang.js +12 -22
  110. package/dist/runtime/utils/object.js +1 -1
  111. package/dist/runtime/utils/select-item.d.ts +3 -1
  112. package/dist/runtime/utils/stop-watch.js +6 -4
  113. package/dist/runtime/utils/string.js +4 -4
  114. package/dist/runtime/utils/tabulator.d.ts +1 -42
  115. package/dist/runtime/utils/tabulator.js +2 -99
  116. package/dist/runtime/utils/theme.d.ts +20 -20
  117. package/dist/runtime/utils/theme.js +180 -30
  118. package/dist/runtime/utils/tv.d.ts +1 -101
  119. package/dist/runtime/utils/tv.js +0 -22
  120. package/dist/types.d.mts +3 -1
  121. package/package.json +61 -119
  122. package/dist/module.cjs +0 -5
  123. package/dist/module.d.ts +0 -16
  124. package/dist/runtime/assets/vue-select.css +0 -1
  125. package/dist/runtime/components/misc/view-name-display-target.vue +0 -39
  126. package/dist/runtime/plugin/v-select.d.ts +0 -2
  127. package/dist/runtime/plugin/v-select.js +0 -5
  128. package/dist/runtime/style.css +0 -22
  129. package/dist/runtime/tailwind.css +0 -78
  130. package/dist/runtime/types/app.config.d.ts +0 -5
  131. package/dist/types.d.ts +0 -1
@@ -1,494 +1,411 @@
1
- <script lang="ts">
2
- /* ----------------------------------------------------------------------------
3
- // src\runtime\components\form\btn.vue
4
- // ----------------------------------------------------------------------------
5
- // Btn
6
- // BtnBtn
7
- ----------------------------------------------------------------------------- */
8
-
9
- // [ utils ]
10
- import { tv } from "../../utils/tv";
11
- import { Theme } from "../../utils/theme";
12
- import { ObjectKeyToMap } from "../../utils/object";
13
- // ----------------------------------------------------------------------------
14
- const buttonTv = tv({
15
- slots: {
16
- base: [
17
- //
18
- `inline-flex items-center`,
19
- `rounded`,
20
- "touch-manipulation ",
21
- `min-w-0 overflow-hidden`,
22
- ],
23
- indicator: [
24
- "pointer-events-none",
25
- `absolute transition-all`,
26
- `border rounded`,
27
- `hover:opacity-60`,
28
- "border-[1px] inset-[-2px] rounded",
29
- ],
30
- overlay: [
31
- "pointer-events-none",
32
- "will-change-transform",
33
- `absolute inset-0`,
34
- "bg-white",
35
- "transition-[opacity_100ms_ease]",
36
- // "z-10",
37
- "opacity-0",
38
- ],
39
- body: [
40
- //
41
- "min-w-0 flex-1",
42
- "pointer-events-none",
43
- "select-none",
44
- ],
45
- },
46
- variants: {
47
- size: {
48
- xs: { base: ["text-[14px] leading-[1.4em] min-h-[32px]"] },
49
- s: { base: ["text-[14px] leading-[1.5em] min-h-[44px]"] },
50
- m: { base: ["text-[16px] leading-[1.5em] min-h-[48px]"] },
51
- l: { base: ["text-[1.2rem] leading-[1.6em] min-h-[60px]"] },
52
- xl: { base: ["text-[1.4rem] leading-[1.6em] min-h-[70px]"] },
53
- },
54
- textAlign: {
55
- left: {
56
- base: "justify-start",
57
- body: "text-left ",
58
- },
59
- center: {
60
- base: "justify-center",
61
- body: "text-center",
62
- },
63
- right: {
64
- base: "justify-end",
65
- body: "text-end",
66
- },
67
- },
68
- wrap: {
69
- true: {
70
- body: "text-wrap whitespace-pre-wrap text-ellipsis overflow-hidden",
71
- },
72
- false: { body: "truncate" },
73
- },
74
- disabled: {
75
- true: {
76
- base: "cursor-default",
77
- // overlay: "opacity-40",
78
- },
79
- false: {
80
- base: "cursor-pointer",
81
- },
82
- },
83
- flash: {
84
- true: "",
85
- false: "",
86
- },
87
- focus: {
88
- true: "",
89
- false: "",
90
- },
91
- hover: {
92
- true: "",
93
- false: "",
94
- },
95
- variant: {
96
- outlined: {
97
- base: "py-1 px-2 border-[2px]",
98
- indicator: "hover:border-[2px] ",
99
- },
100
- flat: {
101
- base: "py-1 px-2 border",
102
- indicator: "hover:border-[2px] ",
103
- },
104
- text: {
105
- base: "border-0 min-h-0 h-auto no-underline",
106
- indicator: "border-0",
107
- },
108
- },
109
- theme: ObjectKeyToMap(Theme, ""),
110
- },
111
- defaultVariants: {
112
- size: "m",
113
- variant: "outlined",
114
- theme: "accent1",
115
- textAlign: "center",
116
- },
117
- compoundVariants: [
118
- {
119
- flash: true,
120
- disabled: false,
121
- class: {
122
- overlay: "opacity-40",
123
- },
124
- },
125
- {
126
- flash: false,
127
- disabled: false,
128
- class: {
129
- overlay: "opacity-0",
130
- },
131
- },
132
-
133
- {
134
- variant: "text",
135
- disabled: false,
136
- class: {
137
- base: "hover:underline",
138
- },
139
- },
140
- {
141
- variant: ["outlined", "flat"],
142
- focus: true,
143
- hover: [true, false],
144
- disabled: false,
145
- class: {
146
- indicator: " border-[3px] inset-[2px] rounded opacity-50",
147
- },
148
- },
149
- {
150
- variant: ["outlined", "flat"],
151
- focus: false,
152
- hover: true,
153
- disabled: false,
154
- class: {
155
- indicator: "border-[2px] inset-[2px] rounded",
156
- },
157
- },
158
- {
159
- variant: ["text"],
160
- focus: true,
161
- hover: [false],
162
- disabled: false,
163
- class: {
164
- base: "underline decoration-dotted",
165
- indicator: "",
166
- overlay: "opacity-0",
167
- },
168
- },
169
- ...Object.keys(Theme).map((theme) => {
170
- return {
171
- theme: theme,
172
- variant: "flat",
173
- class: {
174
- base: [
175
- `bg-[var(--main-color)] border-[var(--main-color)]`,
176
- ["back", "white", "warn"].includes(theme)
177
- ? `text-black `
178
- : "text-white ",
179
- ],
180
- indicator: ["back", "white"].includes(theme)
181
- ? `border-gray-500`
182
- : "border-white",
183
- },
184
- } as any;
185
- }),
186
- ...Object.keys(Theme).map((theme) => {
187
- return {
188
- theme: theme,
189
- variant: "outlined",
190
- class: {
191
- base: [
192
- "bg-transparent",
193
- `text-[var(--main-color)] border-[var(--main-color)]`,
194
- ],
195
- indicator: ["border-current"],
196
- },
197
- } as any;
198
- }),
199
- ...Object.keys(Theme).map((theme) => {
200
- return {
201
- theme: theme,
202
- variant: "text",
203
- class: {
204
- base: ["bg-transparent", `text-[var(--main-color)]`],
205
- indicator: [],
206
- },
207
- } as any;
208
- }),
209
- // disable
210
- {
211
- flash: [false, true],
212
- variant: ["flat"],
213
- disabled: true,
214
- class: {
215
- base: "",
216
- overlay: "opacity-50 ",
217
- },
218
- },
219
- {
220
- flash: [false, true],
221
- variant: ["outlined"],
222
- disabled: true,
223
- class: {
224
- base: [
225
- "bg-transparent",
226
- `text-[var(--main-color)] border-[var(--main-color-opacity-50)]`,
227
- ],
228
- overlay: "opacity-50 ",
229
- },
230
- },
231
- {
232
- flash: [false, true],
233
- variant: ["text"],
234
- disabled: true,
235
- class: {
236
- base: "text-[var(--main-color-opacity-50)] ",
237
- },
238
- },
239
- ],
240
- });
241
- </script>
242
- <script setup lang="ts">
243
- // ----------------------------------------------------------------------------
244
- // [ vueuse ]
245
- import { useElementHover } from "@vueuse/core";
246
- // [ NUXT ]
247
- import { ref, computed, useId } from "#imports";
248
- // [ utils ]
249
- import { Dayjs } from "../../utils/dayjs";
250
- import { type ClassType, ClassTypeToString } from "../../utils/class-style";
251
- import { GetGolorCode } from "../../utils/theme";
252
- import { Sleep } from "../../utils/com";
253
- // [ composables ]
254
- import { useHsFocus } from "../../composables/use-hs-focus";
255
-
256
- import BtnLineLoading from "./btn-line-loading.vue";
257
- // ----------------------------------------------------------------------------
258
- // ----------------------------------------------------------------------------
259
- interface Props {
260
- class?: ClassType;
261
- classInner?: ClassType;
262
- classOverlay?: ClassType;
263
- disabled?: boolean;
264
- to?: string;
265
- theme?: Theme;
266
- variant?: "outlined" | "flat" | "text";
267
- textWrap?: boolean;
268
- textAlign?: "left" | "center" | "right";
269
- loading?: boolean;
270
- noneFocusLine?: boolean;
271
- wrap?: boolean;
272
- // ----------------------------------------------------------------------------
273
- // 設定
274
- size?: "xs" | "s" | "m" | "l" | "xl";
275
- }
276
- const props = withDefaults(defineProps<Props>(), {
277
- class: "",
278
- classInner: "",
279
- classOverlay: "",
280
- to: undefined,
281
- theme: "accent1",
282
- variant: "outlined",
283
- disabled: false,
284
- textWrap: false,
285
- align: "center",
286
- loading: false,
287
- textAlign: "center",
288
- noneFocusLine: false,
289
- wrap: false,
290
- // ----------------------------------------------------------------------------
291
- // 設定
292
- size: "m",
293
- });
294
-
295
- type InputFocusEventArg = {
296
- elm: HTMLElement;
297
- id: string;
298
- };
299
- type Emits = {
300
- id: [id: string];
301
- ref: [element: HTMLElement];
302
- focus: [e: InputFocusEventArg];
303
- blur: [e: InputFocusEventArg];
304
- };
305
- const emit = defineEmits<Emits>();
306
- // ----------------------------------------------------------------------------
307
- const fcFocus = useHsFocus();
308
-
309
- const uid = useId();
310
- emit("id", uid);
311
- // ----------------------------------------------------------------------------
312
- // ----------------------------------------------------------------------------
313
-
314
- const styleMain = computed(() => {
315
- return [
316
- //
317
- `--main-color:${GetGolorCode(props.theme)};`,
318
- `--main-color-opacity-50:${GetGolorCode(props.theme)}88;`,
319
- `--sub-color:${GetGolorCode(props.theme)};`,
320
- ];
321
- });
322
-
323
- const classStyle = computed(() => {
324
- return btnTvBase.value;
325
- });
326
-
327
- // ----------------------------------------------------------------------------
328
- // disabled
329
- const disabled = computed(() => {
330
- if (props.disabled) return true;
331
- if (props.loading) return true;
332
- return false;
333
- });
334
-
335
- // ----------------------------------------------------------------------------
336
-
337
- // [ focus, blur ]
338
- const isActivate = ref(false);
339
-
340
- /** コントロールのFocus判定 */
341
- const computedActivate = computed(() => {
342
- if (disabled.value) return;
343
- if (fcFocus.state.id !== uid) return false;
344
- if (isActivate.value) return true;
345
- // if (flashState.value) return true;
346
- return false;
347
- });
348
-
349
- // focus, blur Event
350
- const imputElm = ref<HTMLElement | null>(null);
351
- const setRef = (e: any) => {
352
- imputElm.value = e;
353
- emit("ref", e);
354
- };
355
- const onFocus = () => {
356
- // console.log("onFocus");
357
- if (disabled.value) return;
358
- isActivate.value = true;
359
- fcFocus.state.id = uid;
360
- const elm = imputElm.value;
361
- if (elm === null) return;
362
- emit("focus", { elm: elm, id: uid });
363
- };
364
- const onBlur = () => {
365
- // console.log("onBlur");
366
- isActivate.value = false;
367
- if (fcFocus.state.id === uid) {
368
- fcFocus.state.id = "";
369
- }
370
- if (disabled.value) return;
371
- const elm = imputElm.value;
372
- if (elm === null) return;
373
- emit("blur", { elm: elm, id: uid });
374
- };
375
-
376
- // ----------------------------------------------------------------------------
377
-
378
- const isHovered = useElementHover(imputElm);
379
-
380
- // ----------------------------------------------------------------------------
381
- const flash = ref(false);
382
- const pushOnTs = ref("");
383
- const pushOn = async (e: any) => {
384
- if (imputElm.value === null) return;
385
- if (disabled.value) return;
386
- const ts = Dayjs().format("");
387
- pushOnTs.value = ts;
388
- flash.value = true;
389
- await Sleep(10000);
390
- if (pushOnTs.value === ts) {
391
- flash.value = false;
392
- }
393
- };
394
-
395
- const pushOff = () => {
396
- flash.value = false;
397
- // isActivate.value = false;
398
- if (props.disabled) return true;
399
- };
400
-
401
- // ----------------------------------------------------------------------------
402
-
403
- const ui = computed(() => {
404
- return buttonTv({
405
- size: props.size,
406
- variant: props.variant,
407
- theme: props.theme,
408
- wrap: props.wrap,
409
- textAlign: props.textAlign,
410
- focus: computedActivate.value,
411
- flash: flash.value,
412
- hover: isHovered.value,
413
- disabled: disabled.value,
414
- });
415
- });
416
-
417
- const btnTvBase = computed(() => {
418
- return ui.value.base({
419
- class: ClassTypeToString(props.class),
420
- });
421
- });
422
-
423
- const btnTvIndicator = computed(() => {
424
- return ui.value.indicator({});
425
- });
426
-
427
- const btnTvBody = computed(() => {
428
- return ui.value.body({
429
- class: ClassTypeToString(props.classInner),
430
- });
431
- });
432
-
433
- const btnTvOverlay = computed(() => {
434
- return ui.value.overlay({
435
- class: ClassTypeToString(props.classOverlay),
436
- });
437
- });
438
-
439
- // ----------------------------------------------------------------------------
440
- </script>
441
-
442
- <template>
443
- <button
444
- v-if="props.to === undefined"
445
- :ref="(e:any) => setRef(e)"
446
- type="button"
447
- :class="btnTvBase"
448
- :style="styleMain"
449
- :disabled="disabled"
450
- @focus="onFocus()"
451
- @blur="onBlur()"
452
- @mousedown="pushOn"
453
- @mouseup="pushOff"
454
- @mouseend="pushOff"
455
- @touchstart="pushOn"
456
- @touchend="pushOff"
457
- @touchcancel="pushOff"
458
- @keydown.enter="pushOn"
459
- @keyup.enter="pushOff"
460
- >
461
- <div :class="btnTvIndicator"></div>
462
- <div :class="btnTvBody">
463
- <slot />
464
- </div>
465
- <div :class="btnTvOverlay"></div>
466
- <BtnLineLoading class="Btn--loading" :show="props.loading" />
467
- </button>
468
- <NuxtLink
469
- v-else
470
- :ref="(e:any) => setRef(e)"
471
- :to="disabled ? undefined : props.to"
472
- :class="classStyle"
473
- :style="styleMain"
474
- :disabled="disabled"
475
- ontouchstart=""
476
- @focus="onFocus()"
477
- @blur="onBlur()"
478
- @mousedown="pushOn"
479
- @mouseup="pushOff"
480
- @mouseend="pushOff"
481
- @touchstart="pushOn"
482
- @touchend="pushOff"
483
- @touchcancel="pushOff"
484
- @keydown.enter="pushOn"
485
- @keyup.enter="pushOff"
486
- >
487
- <div :class="btnTvIndicator"></div>
488
- <div :class="btnTvOverlay"></div>
489
- <div :class="btnTvBody">
490
- <slot />
491
- </div>
492
- <BtnLineLoading class="Btn--loading" :show="props.loading" />
493
- </NuxtLink>
494
- </template>
1
+ <script>
2
+ import { tv } from "../../utils/tv";
3
+ import { Theme } from "../../utils/theme";
4
+ import { ObjectKeyToMap } from "../../utils/object";
5
+ const buttonTv = tv({
6
+ slots: {
7
+ base: [
8
+ //
9
+ "relative",
10
+ `inline-flex items-center`,
11
+ `rounded`,
12
+ "touch-manipulation ",
13
+ `min-w-0 overflow-hidden`
14
+ ],
15
+ indicator: [
16
+ "pointer-events-none",
17
+ `absolute transition-all`,
18
+ `border rounded`,
19
+ `hover:opacity-60`,
20
+ "border-[1px] inset-[-2px] rounded"
21
+ ],
22
+ overlay: [
23
+ "pointer-events-none",
24
+ "will-change-transform",
25
+ `absolute inset-0`,
26
+ "bg-white",
27
+ "transition-[opacity_100ms_ease]",
28
+ // "z-10",
29
+ "opacity-0"
30
+ ],
31
+ body: [
32
+ //
33
+ "min-w-0 flex-1",
34
+ "pointer-events-none",
35
+ "select-none"
36
+ ]
37
+ },
38
+ variants: {
39
+ size: {
40
+ xs: { base: ["text-[14px] leading-[1.4em] min-h-[32px]"] },
41
+ s: { base: ["text-[14px] leading-[1.5em] min-h-[44px]"] },
42
+ m: { base: ["text-[16px] leading-[1.5em] min-h-[48px]"] },
43
+ l: { base: ["text-[1.2rem] leading-[1.6em] min-h-[60px]"] },
44
+ xl: { base: ["text-[1.4rem] leading-[1.6em] min-h-[70px]"] }
45
+ },
46
+ textAlign: {
47
+ left: {
48
+ base: "justify-start",
49
+ body: "text-left "
50
+ },
51
+ center: {
52
+ base: "justify-center",
53
+ body: "text-center"
54
+ },
55
+ right: {
56
+ base: "justify-end",
57
+ body: "text-end"
58
+ }
59
+ },
60
+ wrap: {
61
+ true: {
62
+ body: "text-wrap whitespace-pre-wrap text-ellipsis overflow-hidden"
63
+ },
64
+ false: { body: "truncate" }
65
+ },
66
+ disabled: {
67
+ true: {
68
+ base: "cursor-default"
69
+ // overlay: "opacity-40",
70
+ },
71
+ false: {
72
+ base: "cursor-pointer"
73
+ }
74
+ },
75
+ flash: {
76
+ true: "",
77
+ false: ""
78
+ },
79
+ focus: {
80
+ true: "",
81
+ false: ""
82
+ },
83
+ hover: {
84
+ true: "",
85
+ false: ""
86
+ },
87
+ variant: {
88
+ outlined: {
89
+ base: "py-1 px-2 border-[2px]",
90
+ indicator: "hover:border-[2px] "
91
+ },
92
+ flat: {
93
+ base: "py-1 px-2 border",
94
+ indicator: "hover:border-[2px] "
95
+ },
96
+ text: {
97
+ base: "border-0 min-h-0 h-auto no-underline",
98
+ indicator: "border-0"
99
+ }
100
+ },
101
+ theme: ObjectKeyToMap(Theme, "")
102
+ },
103
+ defaultVariants: {
104
+ size: "m",
105
+ variant: "outlined",
106
+ theme: "accent1",
107
+ textAlign: "center"
108
+ },
109
+ compoundVariants: [
110
+ {
111
+ flash: true,
112
+ disabled: false,
113
+ class: {
114
+ overlay: "opacity-40"
115
+ }
116
+ },
117
+ {
118
+ flash: false,
119
+ disabled: false,
120
+ class: {
121
+ overlay: "opacity-0"
122
+ }
123
+ },
124
+ {
125
+ variant: "text",
126
+ disabled: false,
127
+ class: {
128
+ base: "hover:underline"
129
+ }
130
+ },
131
+ {
132
+ variant: ["outlined", "flat"],
133
+ focus: true,
134
+ hover: [true, false],
135
+ disabled: false,
136
+ class: {
137
+ indicator: " border-[3px] inset-[2px] rounded opacity-50"
138
+ }
139
+ },
140
+ {
141
+ variant: ["outlined", "flat"],
142
+ focus: false,
143
+ hover: true,
144
+ disabled: false,
145
+ class: {
146
+ indicator: "border-[2px] inset-[2px] rounded"
147
+ }
148
+ },
149
+ {
150
+ variant: ["text"],
151
+ focus: true,
152
+ hover: [false],
153
+ disabled: false,
154
+ class: {
155
+ base: "underline decoration-dotted",
156
+ indicator: "",
157
+ overlay: "opacity-0"
158
+ }
159
+ },
160
+ ...Object.keys(Theme).map((theme) => {
161
+ return {
162
+ theme,
163
+ variant: "flat",
164
+ class: {
165
+ base: [
166
+ `bg-[var(--main-color)] border-[var(--main-color)]`,
167
+ ["back", "white", "warn"].includes(theme) ? `text-black ` : "text-white "
168
+ ],
169
+ indicator: ["back", "white"].includes(theme) ? `border-gray-500` : "border-white"
170
+ }
171
+ };
172
+ }),
173
+ ...Object.keys(Theme).map((theme) => {
174
+ return {
175
+ theme,
176
+ variant: "outlined",
177
+ class: {
178
+ base: ["bg-transparent", `text-[var(--main-color)] border-[var(--main-color)]`],
179
+ indicator: ["border-current"]
180
+ }
181
+ };
182
+ }),
183
+ ...Object.keys(Theme).map((theme) => {
184
+ return {
185
+ theme,
186
+ variant: "text",
187
+ class: {
188
+ base: ["bg-transparent", `text-[var(--main-color)]`],
189
+ indicator: []
190
+ }
191
+ };
192
+ }),
193
+ // disable
194
+ {
195
+ flash: [false, true],
196
+ variant: ["flat"],
197
+ disabled: true,
198
+ class: {
199
+ base: "",
200
+ overlay: "opacity-50 "
201
+ }
202
+ },
203
+ {
204
+ flash: [false, true],
205
+ variant: ["outlined"],
206
+ disabled: true,
207
+ class: {
208
+ base: ["bg-transparent", `text-[var(--main-color)] border-[var(--main-color-opacity-50)]`],
209
+ overlay: "opacity-50 "
210
+ }
211
+ },
212
+ {
213
+ flash: [false, true],
214
+ variant: ["text"],
215
+ disabled: true,
216
+ class: {
217
+ base: "text-[var(--main-color-opacity-50)] "
218
+ }
219
+ }
220
+ ]
221
+ });
222
+ </script>
223
+
224
+ <script setup>
225
+ import { useElementHover } from "@vueuse/core";
226
+ import { ref, computed, useId } from "#imports";
227
+ import { Dayjs } from "../../utils/dayjs";
228
+ import { ClassTypeToString } from "../../utils/class-style";
229
+ import { Sleep } from "../../utils/com";
230
+ import { GetColorCode } from "../../utils/theme";
231
+ import { useHsFocus } from "../../composables/use-hs-focus";
232
+ import { useHsPinia } from "../../composables/use-pinia";
233
+ import BtnLineLoading from "./btn-line-loading.vue";
234
+ const props = defineProps({
235
+ class: { type: [String, Object, Array], required: false, default: "" },
236
+ classInner: { type: [String, Object, Array], required: false, default: "" },
237
+ classOverlay: { type: [String, Object, Array], required: false, default: "" },
238
+ disabled: { type: Boolean, required: false, default: false },
239
+ to: { type: String, required: false, default: void 0 },
240
+ theme: { type: null, required: false, default: "accent1" },
241
+ variant: { type: String, required: false, default: "outlined" },
242
+ textWrap: { type: Boolean, required: false, default: false },
243
+ textAlign: { type: String, required: false, default: "center" },
244
+ loading: { type: Boolean, required: false, default: false },
245
+ noneFocusLine: { type: Boolean, required: false, default: false },
246
+ wrap: { type: Boolean, required: false, default: false },
247
+ size: { type: String, required: false, default: "m" }
248
+ });
249
+ const onClick = (e) => {
250
+ if (disabled.value) return;
251
+ emit("click", e);
252
+ };
253
+ const emit = defineEmits(["id", "ref", "focus", "blur", "click"]);
254
+ const fcFocus = useHsFocus(useHsPinia());
255
+ const uid = useId();
256
+ emit("id", uid);
257
+ const styleMain = computed(() => {
258
+ return [
259
+ //
260
+ `--main-color:${GetColorCode(props.theme)};`,
261
+ `--main-color-opacity-50:${GetColorCode(props.theme)}88;`,
262
+ `--sub-color:${GetColorCode(props.theme)};`
263
+ ];
264
+ });
265
+ const classStyle = computed(() => {
266
+ return btnTvBase.value;
267
+ });
268
+ const disabled = computed(() => {
269
+ if (props.disabled) return true;
270
+ if (props.loading) return true;
271
+ return false;
272
+ });
273
+ const isActivate = ref(false);
274
+ const computedActivate = computed(() => {
275
+ if (disabled.value) return;
276
+ if (fcFocus.state.id !== uid) return false;
277
+ if (isActivate.value) return true;
278
+ return false;
279
+ });
280
+ const imputElm = ref(null);
281
+ defineExpose({ el: imputElm });
282
+ const setRef = (e) => {
283
+ imputElm.value = e;
284
+ emit("ref", e);
285
+ };
286
+ const onFocus = () => {
287
+ if (disabled.value) return;
288
+ isActivate.value = true;
289
+ fcFocus.state.id = uid;
290
+ const elm = imputElm.value;
291
+ if (elm === null) return;
292
+ emit("focus", { elm, id: uid });
293
+ };
294
+ const onBlur = () => {
295
+ isActivate.value = false;
296
+ if (fcFocus.state.id === uid) {
297
+ fcFocus.state.id = "";
298
+ }
299
+ if (disabled.value) return;
300
+ const elm = imputElm.value;
301
+ if (elm === null) return;
302
+ emit("blur", { elm, id: uid });
303
+ };
304
+ const isHovered = useElementHover(imputElm);
305
+ const flash = ref(false);
306
+ const pushOnTs = ref("");
307
+ const pushOn = async (e) => {
308
+ if (imputElm.value === null) return;
309
+ if (disabled.value) return;
310
+ const ts = Dayjs().format("");
311
+ pushOnTs.value = ts;
312
+ flash.value = true;
313
+ await Sleep(1e4);
314
+ if (pushOnTs.value === ts) {
315
+ flash.value = false;
316
+ }
317
+ };
318
+ const pushOff = () => {
319
+ flash.value = false;
320
+ if (props.disabled) return true;
321
+ };
322
+ const ui = computed(() => {
323
+ return buttonTv({
324
+ size: props.size,
325
+ variant: props.variant,
326
+ theme: props.theme,
327
+ wrap: props.wrap,
328
+ textAlign: props.textAlign,
329
+ focus: computedActivate.value,
330
+ flash: flash.value,
331
+ hover: isHovered.value,
332
+ disabled: disabled.value
333
+ });
334
+ });
335
+ const btnTvBase = computed(() => {
336
+ return ui.value.base({
337
+ class: ClassTypeToString(props.class)
338
+ });
339
+ });
340
+ const btnTvIndicator = computed(() => {
341
+ return ui.value.indicator({});
342
+ });
343
+ const btnTvBody = computed(() => {
344
+ return ui.value.body({
345
+ class: ClassTypeToString(props.classInner)
346
+ });
347
+ });
348
+ const btnTvOverlay = computed(() => {
349
+ return ui.value.overlay({
350
+ class: ClassTypeToString(props.classOverlay)
351
+ });
352
+ });
353
+ </script>
354
+
355
+ <template>
356
+ <button
357
+ v-if="props.to === void 0"
358
+ :ref="(e) => setRef(e)"
359
+ type="button"
360
+ :class="btnTvBase"
361
+ :style="styleMain"
362
+ :disabled="disabled"
363
+ @focus="onFocus()"
364
+ @blur="onBlur()"
365
+ @mousedown="pushOn"
366
+ @mouseup="pushOff"
367
+ @mouseend="pushOff"
368
+ @touchstart="pushOn"
369
+ @touchend="pushOff"
370
+ @touchcancel="pushOff"
371
+ @keydown.enter="pushOn"
372
+ @keyup.enter="pushOff"
373
+ @click="onClick"
374
+ @keydown.enter.prevent.stop="onClick"
375
+ >
376
+ <div :class="btnTvIndicator"></div>
377
+ <div :class="btnTvBody">
378
+ <slot />
379
+ </div>
380
+ <div :class="btnTvOverlay"></div>
381
+ <BtnLineLoading class="Btn--loading" :show="props.loading" />
382
+ </button>
383
+ <NuxtLink
384
+ v-else
385
+ :ref="(e) => setRef(e)"
386
+ :to="disabled ? void 0 : props.to"
387
+ :class="classStyle"
388
+ :style="styleMain"
389
+ :disabled="disabled"
390
+ ontouchstart=""
391
+ @focus="onFocus()"
392
+ @blur="onBlur()"
393
+ @mousedown="pushOn"
394
+ @mouseup="pushOff"
395
+ @mouseend="pushOff"
396
+ @touchstart="pushOn"
397
+ @touchend="pushOff"
398
+ @touchcancel="pushOff"
399
+ @keydown.enter="pushOn"
400
+ @keyup.enter="pushOff"
401
+ @click="onClick"
402
+ @keydown.enter.prevent.stop="onClick"
403
+ >
404
+ <div :class="btnTvIndicator"></div>
405
+ <div :class="btnTvOverlay"></div>
406
+ <div :class="btnTvBody">
407
+ <slot />
408
+ </div>
409
+ <BtnLineLoading class="Btn--loading" :show="props.loading" />
410
+ </NuxtLink>
411
+ </template>