@witchcraft/ui 0.0.1 → 0.1.1

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 (224) hide show
  1. package/README.md +18 -28
  2. package/dist/module.d.mts +3 -1
  3. package/dist/module.json +3 -3
  4. package/dist/module.mjs +21 -12
  5. package/dist/runtime/assets/base.css +1 -1
  6. package/dist/runtime/assets/locales/en.json +2 -2
  7. package/dist/runtime/assets/tailwind.css +1 -1
  8. package/dist/runtime/assets/utils.css +1 -0
  9. package/dist/runtime/build/WitchcraftUiResolver.js +1 -1
  10. package/dist/runtime/components/Aria/Aria.vue +5 -9
  11. package/dist/runtime/components/Aria/Aria.vue.d.ts +5 -0
  12. package/dist/runtime/components/Icon/Icon.vue +12 -28
  13. package/dist/runtime/components/Icon/Icon.vue.d.ts +21 -0
  14. package/dist/runtime/components/LibButton/LibButton.vue +93 -117
  15. package/dist/runtime/components/LibButton/LibButton.vue.d.ts +36 -0
  16. package/dist/runtime/components/LibCheckbox/LibCheckbox.vue +53 -76
  17. package/dist/runtime/components/LibCheckbox/LibCheckbox.vue.d.ts +42 -0
  18. package/dist/runtime/components/LibColorInput/LibColorInput.vue +131 -101
  19. package/dist/runtime/components/LibColorInput/LibColorInput.vue.d.ts +63 -0
  20. package/dist/runtime/components/LibColorPicker/LibColorPicker.vue +326 -296
  21. package/dist/runtime/components/LibColorPicker/LibColorPicker.vue.d.ts +61 -0
  22. package/dist/runtime/components/LibColorPicker/utils/safeConvertToHsva.d.ts +2 -0
  23. package/dist/runtime/components/LibColorPicker/utils/safeConvertToHsva.js +18 -0
  24. package/dist/runtime/components/LibColorPicker/utils/safeConvertToRgba.d.ts +2 -0
  25. package/dist/runtime/components/LibColorPicker/utils/safeConvertToRgba.js +17 -0
  26. package/dist/runtime/components/LibColorPicker/utils/toLowPrecisionRgbaString.d.ts +2 -0
  27. package/dist/runtime/components/LibColorPicker/utils/toLowPrecisionRgbaString.js +8 -0
  28. package/dist/runtime/components/LibColorPicker/utils/truncate.d.ts +1 -0
  29. package/dist/runtime/components/LibColorPicker/utils/truncate.js +5 -0
  30. package/dist/runtime/components/LibDarkModeSwitcher/LibDarkModeSwitcher.vue +42 -64
  31. package/dist/runtime/components/LibDarkModeSwitcher/LibDarkModeSwitcher.vue.d.ts +22 -0
  32. package/dist/runtime/components/LibDatePicker/LibDatePicker.vue +20 -54
  33. package/dist/runtime/components/LibDatePicker/LibDatePicker.vue.d.ts +40 -0
  34. package/dist/runtime/components/LibDatePicker/LibRangeDatePicker.vue +205 -173
  35. package/dist/runtime/components/LibDatePicker/LibRangeDatePicker.vue.d.ts +34 -0
  36. package/dist/runtime/components/LibDatePicker/LibSingleDatePicker.vue +215 -164
  37. package/dist/runtime/components/LibDatePicker/LibSingleDatePicker.vue.d.ts +34 -0
  38. package/dist/runtime/components/LibDatePicker/LibTimeZonePicker.vue +9 -10
  39. package/dist/runtime/components/LibDatePicker/LibTimeZonePicker.vue.d.ts +22 -0
  40. package/dist/runtime/components/LibDebug/LibDebug.vue +47 -65
  41. package/dist/runtime/components/LibDebug/LibDebug.vue.d.ts +32 -0
  42. package/dist/runtime/components/LibDevOnly/LibDevOnly.vue +19 -34
  43. package/dist/runtime/components/LibDevOnly/LibDevOnly.vue.d.ts +22 -0
  44. package/dist/runtime/components/LibFileInput/LibFileInput.vue +155 -173
  45. package/dist/runtime/components/LibFileInput/LibFileInput.vue.d.ts +43 -0
  46. package/dist/runtime/components/LibInputDeprecated/LibInputDeprecated.vue +352 -0
  47. package/dist/runtime/components/LibInputDeprecated/LibInputDeprecated.vue.d.ts +165 -0
  48. package/dist/runtime/components/LibLabel/LibLabel.vue +30 -46
  49. package/dist/runtime/components/LibLabel/LibLabel.vue.d.ts +27 -0
  50. package/dist/runtime/components/LibMultiValues/LibMultiValues.vue +50 -66
  51. package/dist/runtime/components/LibMultiValues/LibMultiValues.vue.d.ts +29 -0
  52. package/dist/runtime/components/LibNotifications/LibNotification.vue +48 -56
  53. package/dist/runtime/components/LibNotifications/LibNotification.vue.d.ts +17 -0
  54. package/dist/runtime/components/LibNotifications/LibNotifications.vue +71 -83
  55. package/dist/runtime/components/LibNotifications/LibNotifications.vue.d.ts +13 -0
  56. package/dist/runtime/components/LibPagination/LibPagination.vue +86 -131
  57. package/dist/runtime/components/LibPagination/LibPagination.vue.d.ts +104 -0
  58. package/dist/runtime/components/LibPalette/LibPalette.vue +23 -26
  59. package/dist/runtime/components/LibPalette/LibPalette.vue.d.ts +14 -0
  60. package/dist/runtime/components/LibPopup/LibPopup.vue +326 -400
  61. package/dist/runtime/components/LibPopup/LibPopup.vue.d.ts +46 -0
  62. package/dist/runtime/components/LibProgressBar/LibProgressBar.vue +73 -93
  63. package/dist/runtime/components/LibProgressBar/LibProgressBar.vue.d.ts +41 -0
  64. package/dist/runtime/components/LibRecorder/LibRecorder.vue +134 -179
  65. package/dist/runtime/components/LibRecorder/LibRecorder.vue.d.ts +77 -0
  66. package/dist/runtime/components/LibRoot/LibRoot.vue +75 -89
  67. package/dist/runtime/components/LibRoot/LibRoot.vue.d.ts +41 -0
  68. package/dist/runtime/components/LibSimpleInput/LibSimpleInput.vue +51 -82
  69. package/dist/runtime/components/LibSimpleInput/LibSimpleInput.vue.d.ts +35 -0
  70. package/dist/runtime/components/LibSuggestions/LibSuggestions.vue +147 -164
  71. package/dist/runtime/components/LibSuggestions/LibSuggestions.vue.d.ts +94 -0
  72. package/dist/runtime/components/LibTable/LibTable.vue +69 -106
  73. package/dist/runtime/components/LibTable/LibTable.vue.d.ts +45 -0
  74. package/dist/runtime/components/Template/NAME.vue +15 -36
  75. package/dist/runtime/components/Template/NAME.vue.d.ts +17 -0
  76. package/dist/runtime/components/TestControls/TestControls.vue +7 -10
  77. package/dist/runtime/components/TestControls/TestControls.vue.d.ts +5 -0
  78. package/dist/runtime/components/index.d.ts +12 -11
  79. package/dist/runtime/components/index.js +12 -11
  80. package/dist/runtime/components/shared/props.d.ts +81 -16
  81. package/dist/runtime/components/shared/storyHelpers/playInput.js +5 -5
  82. package/dist/runtime/components/shared/storyHelpers/playSuggestions.js +15 -11
  83. package/dist/runtime/composables/index.d.ts +5 -0
  84. package/dist/runtime/composables/index.js +5 -0
  85. package/dist/runtime/composables/useDivideAttrs.js +1 -0
  86. package/dist/runtime/composables/useDragWithThreshold.d.ts +71 -0
  87. package/dist/runtime/composables/useDragWithThreshold.js +40 -0
  88. package/dist/runtime/composables/usePreHydrationValue.d.ts +12 -0
  89. package/dist/runtime/composables/usePreHydrationValue.js +15 -0
  90. package/dist/runtime/composables/useSetupI18n.d.ts +2 -0
  91. package/dist/runtime/composables/useSetupI18n.js +5 -1
  92. package/dist/runtime/composables/useSuggestions.d.ts +7 -5
  93. package/dist/runtime/composables/useSuggestions.js +94 -57
  94. package/dist/runtime/directives/vResizableCols.js +92 -84
  95. package/dist/runtime/helpers/NotificationHandler.d.ts +5 -0
  96. package/dist/runtime/helpers/index.d.ts +3 -1
  97. package/dist/runtime/helpers/index.js +3 -1
  98. package/dist/runtime/types/index.d.ts +6 -0
  99. package/dist/runtime/utils/notifyIfError.d.ts +14 -0
  100. package/dist/runtime/utils/notifyIfError.js +29 -0
  101. package/dist/types.d.mts +2 -6
  102. package/package.json +27 -29
  103. package/src/module.ts +31 -12
  104. package/src/runtime/assets/base.css +10 -1
  105. package/src/runtime/assets/locales/en.json +2 -2
  106. package/src/runtime/assets/tailwind.css +1 -1
  107. package/src/runtime/assets/{style.css → utils.css} +86 -4
  108. package/src/runtime/build/WitchcraftUiResolver.ts +1 -1
  109. package/src/runtime/components/Focus.stories.ts +3 -2
  110. package/src/runtime/components/Icon/Icon.vue +10 -6
  111. package/src/runtime/components/LibButton/LibButton.vue +41 -47
  112. package/src/runtime/components/LibCheckbox/LibCheckbox.vue +7 -4
  113. package/src/runtime/components/LibColorInput/LibColorInput.vue +111 -37
  114. package/src/runtime/components/LibColorPicker/LibColorPicker.stories.ts +25 -4
  115. package/src/runtime/components/LibColorPicker/LibColorPicker.vue +242 -131
  116. package/src/runtime/components/LibColorPicker/utils/safeConvertToHsva.ts +24 -0
  117. package/src/runtime/components/LibColorPicker/utils/safeConvertToRgba.ts +23 -0
  118. package/src/runtime/components/LibColorPicker/utils/toLowPrecisionRgbaString.ts +13 -0
  119. package/src/runtime/components/LibColorPicker/utils/truncate.ts +6 -0
  120. package/src/runtime/components/LibDarkModeSwitcher/LibDarkModeSwitcher.stories.ts +1 -1
  121. package/src/runtime/components/LibDarkModeSwitcher/LibDarkModeSwitcher.vue +11 -9
  122. package/src/runtime/components/LibDatePicker/LibDatePicker.vue +4 -17
  123. package/src/runtime/components/LibDatePicker/LibRangeDatePicker.vue +192 -131
  124. package/src/runtime/components/LibDatePicker/LibSingleDatePicker.vue +183 -115
  125. package/src/runtime/components/LibDatePicker/LibTimeZonePicker.vue +3 -3
  126. package/src/runtime/components/LibDebug/LibDebug.vue +15 -5
  127. package/src/runtime/components/LibDevOnly/LibDevOnly.vue +1 -3
  128. package/src/runtime/components/LibFileInput/LibFileInput.vue +54 -29
  129. package/src/runtime/components/{LibInput/LibInput.stories.ts → LibInputDeprecated/LibInputDeprecated.stories.ts} +64 -19
  130. package/{dist/runtime/components/LibInput/LibInput.vue → src/runtime/components/LibInputDeprecated/LibInputDeprecated.vue} +40 -34
  131. package/src/runtime/components/LibLabel/LibLabel.vue +2 -2
  132. package/src/runtime/components/LibMultiValues/LibMultiValues.stories.ts +5 -4
  133. package/src/runtime/components/LibMultiValues/LibMultiValues.vue +11 -13
  134. package/src/runtime/components/LibNotifications/LibNotification.vue +19 -11
  135. package/src/runtime/components/LibNotifications/LibNotifications.stories.ts +2 -2
  136. package/src/runtime/components/LibNotifications/LibNotifications.vue +20 -12
  137. package/src/runtime/components/LibPagination/LibPagination.stories.ts +2 -2
  138. package/src/runtime/components/LibPagination/LibPagination.vue +19 -20
  139. package/src/runtime/components/LibPalette/LibPalette.vue +3 -3
  140. package/src/runtime/components/LibPopup/LibPopup.stories.ts +2 -2
  141. package/src/runtime/components/LibPopup/LibPopup.vue +30 -67
  142. package/src/runtime/components/LibProgressBar/LibProgressBar.vue +3 -2
  143. package/src/runtime/components/LibRecorder/LibRecorder.vue +2 -3
  144. package/src/runtime/components/LibRoot/LibRoot.vue +14 -1
  145. package/src/runtime/components/LibSimpleInput/LibSimpleInput.stories.ts +1 -1
  146. package/src/runtime/components/LibSimpleInput/LibSimpleInput.vue +5 -8
  147. package/src/runtime/components/LibSuggestions/LibSuggestions.vue +42 -26
  148. package/src/runtime/components/LibTable/LibTable.vue +8 -9
  149. package/src/runtime/components/Scrolling.stories.ts +58 -0
  150. package/src/runtime/components/Template/NAME.vue +1 -1
  151. package/src/runtime/components/TestControls/TestControls.vue +1 -1
  152. package/src/runtime/components/index.ts +12 -12
  153. package/src/runtime/components/shared/props.ts +82 -19
  154. package/src/runtime/components/shared/storyHelpers/playInput.ts +6 -5
  155. package/src/runtime/components/shared/storyHelpers/playSuggestions.ts +25 -11
  156. package/src/runtime/composables/index.ts +5 -0
  157. package/src/runtime/composables/useDarkMode.ts +2 -2
  158. package/src/runtime/composables/useDivideAttrs.ts +1 -0
  159. package/src/runtime/composables/useDragWithThreshold.ts +108 -0
  160. package/src/runtime/composables/usePreHydrationValue.ts +30 -0
  161. package/src/runtime/composables/useSetupI18n.ts +8 -2
  162. package/src/runtime/composables/useSuggestions.ts +92 -45
  163. package/src/runtime/directives/vResizableCols.ts +82 -74
  164. package/src/runtime/helpers/NotificationHandler.ts +5 -0
  165. package/src/runtime/helpers/index.ts +3 -1
  166. package/src/runtime/types/index.ts +5 -0
  167. package/src/runtime/utils/notifyIfError.ts +45 -0
  168. package/dist/module.cjs +0 -5
  169. package/dist/module.d.ts +0 -34
  170. package/dist/runtime/assets/style.css +0 -1
  171. package/dist/runtime/components/Focus.stories.d.ts +0 -11
  172. package/dist/runtime/components/Focus.stories.js +0 -53
  173. package/dist/runtime/components/LibButton/LibButton.stories.d.ts +0 -12
  174. package/dist/runtime/components/LibButton/LibButton.stories.js +0 -94
  175. package/dist/runtime/components/LibCheckbox/LibCheckbox.stories.d.ts +0 -14
  176. package/dist/runtime/components/LibCheckbox/LibCheckbox.stories.js +0 -29
  177. package/dist/runtime/components/LibColorInput/LibColorInput.stories.d.ts +0 -7
  178. package/dist/runtime/components/LibColorInput/LibColorInput.stories.js +0 -58
  179. package/dist/runtime/components/LibColorPicker/LibColorPicker.stories.d.ts +0 -7
  180. package/dist/runtime/components/LibColorPicker/LibColorPicker.stories.js +0 -51
  181. package/dist/runtime/components/LibDarkModeSwitcher/LibDarkModeSwitcher.stories.d.ts +0 -7
  182. package/dist/runtime/components/LibDarkModeSwitcher/LibDarkModeSwitcher.stories.js +0 -36
  183. package/dist/runtime/components/LibDatePicker/LibDatePicker.stories.d.ts +0 -11
  184. package/dist/runtime/components/LibDatePicker/LibDatePicker.stories.js +0 -98
  185. package/dist/runtime/components/LibDebug/LibDebug.stories.d.ts +0 -9
  186. package/dist/runtime/components/LibDebug/LibDebug.stories.js +0 -46
  187. package/dist/runtime/components/LibFileInput/LibFileInput.stories.d.ts +0 -10
  188. package/dist/runtime/components/LibFileInput/LibFileInput.stories.js +0 -63
  189. package/dist/runtime/components/LibInput/LibInput.stories.d.ts +0 -33
  190. package/dist/runtime/components/LibInput/LibInput.stories.js +0 -339
  191. package/dist/runtime/components/LibLabel/LibLabel.stories.d.ts +0 -6
  192. package/dist/runtime/components/LibLabel/LibLabel.stories.js +0 -25
  193. package/dist/runtime/components/LibMultiValues/LibMultiValues.stories.d.ts +0 -23
  194. package/dist/runtime/components/LibMultiValues/LibMultiValues.stories.js +0 -60
  195. package/dist/runtime/components/LibNotifications/LibNotification.stories.d.ts +0 -15
  196. package/dist/runtime/components/LibNotifications/LibNotification.stories.js +0 -126
  197. package/dist/runtime/components/LibNotifications/LibNotifications.stories.d.ts +0 -6
  198. package/dist/runtime/components/LibNotifications/LibNotifications.stories.js +0 -109
  199. package/dist/runtime/components/LibPagination/LibPagination.stories.d.ts +0 -6
  200. package/dist/runtime/components/LibPagination/LibPagination.stories.js +0 -40
  201. package/dist/runtime/components/LibPalette/LibPalette.stories.d.ts +0 -6
  202. package/dist/runtime/components/LibPalette/LibPalette.stories.js +0 -20
  203. package/dist/runtime/components/LibPopup/LibPopup.stories.d.ts +0 -14
  204. package/dist/runtime/components/LibPopup/LibPopup.stories.js +0 -147
  205. package/dist/runtime/components/LibProgressBar/LibProgressBar.stories.d.ts +0 -10
  206. package/dist/runtime/components/LibProgressBar/LibProgressBar.stories.js +0 -81
  207. package/dist/runtime/components/LibRecorder/LibRecorder.stories.d.ts +0 -19
  208. package/dist/runtime/components/LibRecorder/LibRecorder.stories.js +0 -63
  209. package/dist/runtime/components/LibSimpleInput/LibSimpleInput.stories.d.ts +0 -26
  210. package/dist/runtime/components/LibSimpleInput/LibSimpleInput.stories.js +0 -78
  211. package/dist/runtime/components/LibSuggestions/LibSuggestions.stories.d.ts +0 -27
  212. package/dist/runtime/components/LibSuggestions/LibSuggestions.stories.js +0 -112
  213. package/dist/runtime/components/LibTable/LibTable.stories.d.ts +0 -16
  214. package/dist/runtime/components/LibTable/LibTable.stories.js +0 -156
  215. package/dist/runtime/components/reset.stories.d.ts +0 -5
  216. package/dist/runtime/components/reset.stories.js +0 -19
  217. package/dist/runtime/composables/useScrollNearContainerEdges.stories.d.ts +0 -7
  218. package/dist/runtime/composables/useScrollNearContainerEdges.stories.js +0 -85
  219. package/dist/runtime/helpers/addValue.d.ts +0 -1
  220. package/dist/runtime/helpers/addValue.js +0 -8
  221. package/dist/types.d.ts +0 -7
  222. package/src/runtime/components/LibInput/LibInput.vue +0 -372
  223. package/src/runtime/helpers/addValue.ts +0 -10
  224. /package/src/runtime/components/{reset.stories.ts → Reset.stories.ts} +0 -0
@@ -4,8 +4,9 @@
4
4
  contenteditable=false is because of storybook, it's shortcuts interfere when not using real input elements
5
5
  -->
6
6
  <div
7
- :id="id?? fallbackId"
8
- :class="twMerge(`recorder
7
+ :id="id ?? fallbackId"
8
+ :class="twMerge(
9
+ `recorder
9
10
  flex items-center
10
11
  gap-2
11
12
  px-2
@@ -13,37 +14,38 @@
13
14
  focus-outline-no-offset
14
15
  rounded-sm
15
16
  `,
16
- border &&`
17
+ border && `
17
18
  border
18
19
  border-neutral-500
19
20
  focus:border-accent-500
20
21
  `,
21
-
22
- (disabled || readonly) && `
22
+ (disabled || readonly) && `
23
23
  text-neutral-400
24
24
  dark:text-neutral-600
25
25
  `,
26
- (disabled || readonly) && border && `
26
+ (disabled || readonly) && border && `
27
27
  bg-neutral-50
28
28
  dark:bg-neutral-950
29
29
  border-neutral-400
30
30
  dark:border-neutral-600
31
- `
32
- , ($attrs as any).class)"
31
+ `,
32
+ $attrs.class
33
+ )"
33
34
  :aria-disabled="disabled"
34
35
  :aria-readonly="readonly"
35
36
  :tabindex="disabled ? -1 : 0"
36
37
  :title="recording ? recordingTitle : tempValue"
37
38
  contenteditable="false"
38
39
  ref="recorderEl"
39
- v-bind="{...ariaLabel, ...$attrs, class:undefined}"
40
+ v-bind="{ ...ariaLabel, ...$attrs, class: void 0 }"
40
41
  @blur="handleBlurRecorder($event)"
41
42
  @click="handleClickRecorder($event)"
42
43
  @keydown.space.prevent="handleClickRecorder($event, true)"
43
44
  >
44
45
  <!-- :aria-description="recording ? recordingTitle : ''" -->
45
46
  <div
46
- :class="twMerge(`recorder-indicator
47
+ :class="twMerge(
48
+ `recorder--indicator
47
49
  inline-block
48
50
  bg-red-700
49
51
  rounded-full
@@ -52,192 +54,145 @@
52
54
  shrink-0
53
55
  hover:bg-red-500
54
56
  `,
55
- recording && `
57
+ recording && `
56
58
  animate-[blink_1s_infinite]
57
59
  bg-red-500
58
60
  `,
59
- (disabled || readonly) && `
61
+ (disabled || readonly) && `
60
62
  bg-neutral-500
61
63
  `
62
- )"
64
+ )"
63
65
  ref="recorderIndicatorEl"
64
66
  />
65
- <div class="recorder-value before:content-vertical-holder truncate">
66
- {{ recording
67
- ? recordingValue ?? t("recorder.recording")
68
- : tempValue }}
67
+ <div class="recorder--value before:content-vertical-holder truncate">
68
+ {{ recording ? recordingValue ?? t("recorder.recording") : tempValue }}
69
69
  </div>
70
70
  </div>
71
71
  </template>
72
- <script setup lang="ts">
73
- import { keys } from "@alanscodelog/utils/keys.js"
74
- import { computed, type HTMLAttributes ,onBeforeUnmount, onMounted, type PropType, ref, watch, watchPostEffect } from "vue"
75
-
76
- import { useAriaLabel } from "../../composables/useAriaLabel.js"
77
- import { useInjectedI18n } from "../../composables/useInjectedI18n.js"
78
- import { twMerge } from "../../utils/twMerge.js"
79
- import { type BaseInteractiveProps, baseInteractivePropsDefaults, getFallbackId, type LabelProps, type LinkableByIdProps,type TailwindClassProp } from "../shared/props.js"
80
72
 
73
+ <script setup>
74
+ import { keys } from "@alanscodelog/utils/keys.js";
75
+ import { computed, onBeforeUnmount, onMounted, ref, watch, watchPostEffect } from "vue";
76
+ import { useAriaLabel } from "../../composables/useAriaLabel.js";
77
+ import { useInjectedI18n } from "../../composables/useInjectedI18n.js";
78
+ import { twMerge } from "../../utils/twMerge.js";
79
+ import { baseInteractivePropsDefaults, getFallbackId } from "../shared/props.js";
81
80
  defineOptions({
82
- name: "lib-recorder",
83
- inheritAttrs: false,
84
- })
85
- const t = useInjectedI18n()
86
-
87
- const emits = defineEmits<{
88
- /** Recorder is blurred */
89
- (e: "recorder:blur", $event: FocusEvent): void
90
- /** Recorder is clicked. The component's indicator and recorder elements are passed to help filter out those clicks. */
91
- (e: "recorder:click", { event, indicator, input }: { event: MouseEvent | KeyboardEvent, indicator: HTMLElement, input: HTMLInputElement }): void
92
- /* User presses enter. Not emitted when multiple values are used. */
93
- (e: "focus:parent"): void
94
- }>()
95
- const fallbackId = getFallbackId()
96
- // eslint-disable-next-line no-use-before-define
97
- const props = withDefaults(defineProps<Props>(), {
98
- recordingTitle: "",
99
- id: undefined,
100
- binders: undefined,
101
- recorder: undefined,
102
- ...baseInteractivePropsDefaults
103
- })
104
- /**
105
- * Puts the element into recording mode if true. See {@link props.recorder}.
106
- */
107
- const recording = defineModel<boolean>("recording", { required: false, default: false })
108
-
109
- /** The final value of the recorder. For intermediate values while recording, pass a recorder and set an appropriate recording value. */
110
- const modelValue = defineModel<string>({ required: true })
111
-
112
-
113
- const recorderEl = ref<HTMLInputElement | null>(null)
114
- const recorderIndicatorEl = ref<HTMLElement | null>(null)
115
- const canEdit = computed(() => !props.disabled && !props.readonly)
116
- const tempValue = ref(modelValue.value)
117
-
81
+ name: "lib-recorder",
82
+ inheritAttrs: false
83
+ });
84
+ const t = useInjectedI18n();
85
+ const emits = defineEmits(["recorder:blur", "recorder:click", "focus:parent"]);
86
+ const fallbackId = getFallbackId();
87
+ const props = defineProps(/* @__PURE__ */ _mergeDefaults({
88
+ id: { type: String, required: false },
89
+ disabled: { type: Boolean, required: false },
90
+ readonly: { type: Boolean, required: false },
91
+ border: { type: Boolean, required: false },
92
+ unstyle: { type: Boolean, required: false },
93
+ label: { type: String, required: false },
94
+ recordingValue: { type: String, required: false },
95
+ recordingTitle: { type: String, required: false },
96
+ recorder: { type: null, required: false },
97
+ binders: { type: null, required: false }
98
+ }, {
99
+ recordingTitle: "",
100
+ id: void 0,
101
+ binders: void 0,
102
+ recorder: void 0,
103
+ ...baseInteractivePropsDefaults
104
+ }));
105
+ const recording = defineModel("recording", { type: Boolean, ...{ required: false, default: false } });
106
+ const modelValue = defineModel({ type: String, ...{ required: true } });
107
+ const recorderEl = ref(null);
108
+ const recorderIndicatorEl = ref(null);
109
+ const canEdit = computed(() => !props.disabled && !props.readonly);
110
+ const tempValue = ref(modelValue.value);
118
111
  watch([() => props.binders, () => props.binders], () => {
119
- if (recording.value) {
120
- throw new Error("Component was not designed to allow swapping out of binders/recorders while recording")
121
- }
122
- })
123
-
112
+ if (recording.value) {
113
+ throw new Error("Component was not designed to allow swapping out of binders/recorders while recording");
114
+ }
115
+ });
124
116
  watch(modelValue, () => {
125
- tempValue.value = modelValue.value
126
- })
127
- const ariaLabel = useAriaLabel(props)
128
-
129
- const boundListeners: Record<string, any> = {}
130
- let isBound = false
131
-
132
- const unbindListeners = (): void => {
133
- if (!isBound) return
134
- isBound = false
135
- if (props.recorder) {
136
- for (const key of keys(boundListeners)) {
137
- recorderEl.value?.removeEventListener(key, boundListeners[key])
138
- delete boundListeners[key]
139
- }
140
- }
141
- if (props.binders && recorderEl.value) {
142
- props.binders.unbind(recorderEl.value as HTMLInputElement)
143
- }
144
- }
145
- const bindListeners = (): void => {
146
- if (!props.recorder && !props.binders) {
147
- throw new Error("Record is true but no recorder or binders props was passed")
148
- }
149
- if (props.recorder && props.binders) {
150
- throw new Error("Recording is true and was passed both a recorder and a binders prop. Both cannot be used at the same time.")
151
- }
152
- isBound = true
153
- if (props.recorder) {
154
- for (const key of keys(props.recorder)) {
155
- recorderEl.value?.addEventListener(key, props.recorder[key], { passive: false })
156
- boundListeners[key] = props.recorder[key]
157
- }
158
- }
159
- if (props.binders && recorderEl.value) {
160
- props.binders.bind(recorderEl.value as HTMLInputElement)
161
- }
162
- }
163
-
117
+ tempValue.value = modelValue.value;
118
+ });
119
+ const ariaLabel = useAriaLabel(props);
120
+ const boundListeners = {};
121
+ let isBound = false;
122
+ const unbindListeners = () => {
123
+ if (!isBound) return;
124
+ isBound = false;
125
+ if (props.recorder) {
126
+ for (const key of keys(boundListeners)) {
127
+ recorderEl.value?.removeEventListener(key, boundListeners[key]);
128
+ delete boundListeners[key];
129
+ }
130
+ }
131
+ if (props.binders && recorderEl.value) {
132
+ props.binders.unbind(recorderEl.value);
133
+ }
134
+ };
135
+ const bindListeners = () => {
136
+ if (!props.recorder && !props.binders) {
137
+ throw new Error("Record is true but no recorder or binders props was passed");
138
+ }
139
+ if (props.recorder && props.binders) {
140
+ throw new Error("Recording is true and was passed both a recorder and a binders prop. Both cannot be used at the same time.");
141
+ }
142
+ isBound = true;
143
+ if (props.recorder) {
144
+ for (const key of keys(props.recorder)) {
145
+ recorderEl.value?.addEventListener(key, props.recorder[key], { passive: false });
146
+ boundListeners[key] = props.recorder[key];
147
+ }
148
+ }
149
+ if (props.binders && recorderEl.value) {
150
+ props.binders.bind(recorderEl.value);
151
+ }
152
+ };
164
153
  watchPostEffect(() => {
165
- if (!canEdit.value) {
166
- unbindListeners()
167
- recording.value = false
168
- return
169
- }
170
- if (recording.value) {
171
- bindListeners()
172
- } else {
173
- if ((props.recorder || props.binders) && isBound) {
174
- unbindListeners()
175
- // if we just blur the input then we can't shift+tab backwards
176
- // this way we can go forwards or backwards without actually focusing since parentEl is not focusable
177
- // parentEl.value?.focus()
178
- emits("focus:parent")
179
- }
180
- }
181
- })
182
-
154
+ if (!canEdit.value) {
155
+ unbindListeners();
156
+ recording.value = false;
157
+ return;
158
+ }
159
+ if (recording.value) {
160
+ bindListeners();
161
+ } else {
162
+ if ((props.recorder || props.binders) && isBound) {
163
+ unbindListeners();
164
+ emits("focus:parent");
165
+ }
166
+ }
167
+ });
183
168
  onBeforeUnmount(() => {
184
- unbindListeners()
185
- })
169
+ unbindListeners();
170
+ });
186
171
  onMounted(() => {
187
- if (recording.value) {
188
- bindListeners()
189
- }
190
- })
191
-
192
- const handleBlurRecorder = (e: FocusEvent): void => {
193
- if (!canEdit.value) return
194
- if (props.recorder || props.binders) {
195
- emits("recorder:blur", e)
196
- }
197
- }
198
-
199
- const handleClickRecorder = (e: MouseEvent | KeyboardEvent, isSpaceKey: boolean = false): void => {
200
- if (!canEdit.value) return
201
- if (!recording.value) {
202
- recorderEl.value?.focus()
203
- }
204
- // toggle if clicking on the recording indicator, otherwise only allow starting recording, so if needed, clicks can be recorded
205
- if (props.recorder || props.binders) {
206
- if (isSpaceKey) { return }
207
- emits("recorder:click", { event: e as MouseEvent, indicator: recorderIndicatorEl.value! as HTMLElement, input: recorderEl.value! as HTMLInputElement })
208
- }
209
- }
210
-
172
+ if (recording.value) {
173
+ bindListeners();
174
+ }
175
+ });
176
+ const handleBlurRecorder = (e) => {
177
+ if (!canEdit.value) return;
178
+ if (props.recorder || props.binders) {
179
+ emits("recorder:blur", e);
180
+ }
181
+ };
182
+ const handleClickRecorder = (e, isSpaceKey = false) => {
183
+ if (!canEdit.value) return;
184
+ if (!recording.value) {
185
+ recorderEl.value?.focus();
186
+ }
187
+ if (props.recorder || props.binders) {
188
+ if (isSpaceKey) {
189
+ return;
190
+ }
191
+ emits("recorder:click", { event: e, indicator: recorderIndicatorEl.value, input: recorderEl.value });
192
+ }
193
+ };
211
194
  </script>
212
- <script lang="ts">
213
- type RealProps =
214
- & LinkableByIdProps
215
- & BaseInteractiveProps
216
- & LabelProps
217
- & {
218
- border?: boolean
219
- /** A value to display while recording, if none given the i18n `recorder.recording` key is used. */
220
- recordingValue?: string
221
- /** A title to display on the input div while recording. Is also used as the aria-description. */
222
- recordingTitle?: string
223
- /**
224
- * The recorder object is a series of event listeners to attach to the input div while recording is started. If you need to bind directly to the element, see the `binders` prop.
225
- *
226
- * The listeners are then unbound when recording is set to false again.
227
- *
228
- * Note that the component does not handle the setting of `recording` (unless the component is disabled), `modelValue`, or `recordingValue` at all and has no mechanism for cancelling a recording. It is left to the recorder listeners and any `recorder:*` handlers to determine what to do.
229
- */
230
- recorder?: undefined | Record<string, any>
231
- /** This provides a way to manually attach/remove event listeners to/from the element. It is an alternative to the `recorder` prop, see it for more details. Both cannot be specified at the same time.*/
232
- binders?: undefined | { bind: (el: HTMLElement) => void, unbind: (el: HTMLElement) => void }
233
- /** The id of the element. If not provided, the id will be generated automatically. */
234
- id?: string
235
- }
236
195
 
237
- interface Props
238
- extends
239
- /** @vue-ignore */
240
- Partial<Omit<HTMLAttributes,"class"> & TailwindClassProp>,
241
- RealProps
242
- { }
196
+ <script>
197
+
243
198
  </script>
@@ -0,0 +1,77 @@
1
+ import { type HTMLAttributes } from "vue";
2
+ import { type BaseInteractiveProps, type LabelProps, type LinkableByIdProps, type TailwindClassProp } from "../shared/props.js.js";
3
+ type RealProps = LinkableByIdProps & BaseInteractiveProps & LabelProps & {
4
+ border?: boolean;
5
+ /** A value to display while recording, if none given the i18n `recorder.recording` key is used. */
6
+ recordingValue?: string;
7
+ /** A title to display on the input div while recording. Is also used as the aria-description. */
8
+ recordingTitle?: string;
9
+ /**
10
+ * The recorder object is a series of event listeners to attach to the input div while recording is started. If you need to bind directly to the element, see the `binders` prop.
11
+ *
12
+ * The listeners are then unbound when recording is set to false again.
13
+ *
14
+ * Note that the component does not handle the setting of `recording` (unless the component is disabled), `modelValue`, or `recordingValue` at all and has no mechanism for cancelling a recording. It is left to the recorder listeners and any `recorder:*` handlers to determine what to do.
15
+ */
16
+ recorder?: undefined | Record<string, any>;
17
+ /** This provides a way to manually attach/remove event listeners to/from the element. It is an alternative to the `recorder` prop, see it for more details. Both cannot be specified at the same time.*/
18
+ binders?: undefined | {
19
+ bind: (el: HTMLElement) => void;
20
+ unbind: (el: HTMLElement) => void;
21
+ };
22
+ /** The id of the element. If not provided, the id will be generated automatically. */
23
+ id?: string;
24
+ };
25
+ interface Props extends
26
+ /** @vue-ignore */
27
+ Partial<Omit<HTMLAttributes, "class"> & TailwindClassProp>, RealProps {
28
+ }
29
+ declare const _default: import("vue").DefineComponent<Props & {
30
+ /**
31
+ * Puts the element into recording mode if true. See {@link props.recorder}.
32
+ */
33
+ recording?: boolean;
34
+ /** The final value of the recorder. For intermediate values while recording, pass a recorder and set an appropriate recording value. */
35
+ modelValue: string;
36
+ }, void, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
37
+ "update:modelValue": (value: string) => any;
38
+ "update:recording": (value: boolean) => any;
39
+ } & {
40
+ "recorder:blur": ($event: FocusEvent) => any;
41
+ "recorder:click": (args_0: {
42
+ event: MouseEvent | KeyboardEvent;
43
+ indicator: HTMLElement;
44
+ input: HTMLInputElement;
45
+ }) => any;
46
+ "focus:parent": () => any;
47
+ }, string, import("vue").PublicProps, Readonly<Props & {
48
+ /**
49
+ * Puts the element into recording mode if true. See {@link props.recorder}.
50
+ */
51
+ recording?: boolean;
52
+ /** The final value of the recorder. For intermediate values while recording, pass a recorder and set an appropriate recording value. */
53
+ modelValue: string;
54
+ }> & Readonly<{
55
+ "onUpdate:modelValue"?: ((value: string) => any) | undefined;
56
+ "onUpdate:recording"?: ((value: boolean) => any) | undefined;
57
+ "onRecorder:blur"?: (($event: FocusEvent) => any) | undefined;
58
+ "onRecorder:click"?: ((args_0: {
59
+ event: MouseEvent | KeyboardEvent;
60
+ indicator: HTMLElement;
61
+ input: HTMLInputElement;
62
+ }) => any) | undefined;
63
+ "onFocus:parent"?: (() => any) | undefined;
64
+ }>, {
65
+ id: string;
66
+ disabled: boolean;
67
+ readonly: boolean;
68
+ border: boolean;
69
+ unstyle: boolean;
70
+ recordingTitle: string;
71
+ recorder: Record<string, any>;
72
+ binders: {
73
+ bind: (el: HTMLElement) => void;
74
+ unbind: (el: HTMLElement) => void;
75
+ };
76
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
77
+ export default _default;
@@ -2,125 +2,111 @@
2
2
  <div :id="id"
3
3
  tabindex="-1"
4
4
  :class="twMerge(
5
- (showOutline ? 'group outlined outlined-visible' : '[&_*]:outline-hidden'),
6
- darkMode && ' dark',
7
- ($attrs['wrapperAttrs'] as any)?.class
8
- )"
9
- v-bind="{ ...($attrs['wrapperAttrs']), attrs:undefined, class: undefined }"
5
+ showOutline ? 'group outlined outlined-visible' : '[&_*]:outline-hidden',
6
+ darkMode && ' dark',
7
+ $attrs['wrapperAttrs']?.class
8
+ )"
9
+ v-bind="{ ...$attrs['wrapperAttrs'], attrs: void 0, class: void 0 }"
10
10
  :ref="handleRef"
11
11
  >
12
12
  <!-- id root is useful for teleports, so they are at the topmost level where they can still be styled -->
13
13
  <!-- See TestControls for why the margins here -->
14
14
  <div
15
15
  id="root"
16
- v-bind="{ ...$attrs.attrs, class: undefined, wrapperAttrs: undefined }"
17
- :class="twMerge( `
16
+ v-bind="{ ...$attrs.attrs, class: void 0, wrapperAttrs: void 0 }"
17
+ :class="twMerge(
18
+ `
18
19
  dark:bg-fg
19
20
  dark:text-bg
20
21
  bg-bg
21
22
  text-fg
22
23
  `,
23
- testWrapperMode && `
24
+ testWrapperMode && `
24
25
  px-10
25
26
  pb-10
26
27
  `,
27
- !testWrapperMode && `
28
+ !testWrapperMode && `
28
29
  min-h-dvh
29
30
  flex
30
31
  flex-col
31
32
  `,
32
- ($attrs as any).attrs?.class)"
33
+ $attrs.attrs?.class
34
+ )"
33
35
  >
34
36
  <TestControls v-if="testWrapperMode" :show-outline="showOutline"/>
37
+ <Notifications v-if="useNotifications && isClientSide"/>
35
38
  <slot/>
36
39
  </div>
37
40
  </div>
38
41
  </template>
39
42
 
40
- <script setup lang="ts">
41
- import { unreachable } from "@alanscodelog/utils/unreachable.js"
42
- import { type Theme } from "metamorphosis"
43
- import { type ComponentPublicInstance, computed, onBeforeUnmount, onMounted, ref, toRaw } from "vue"
44
-
45
- import { useAccesibilityOutline } from "../../composables/useAccesibilityOutline.js"
46
- import { useDivideAttrs } from "../../composables/useDivideAttrs.js"
47
- import { useSetupDarkMode } from "../../composables/useSetupDarkMode.js"
48
- import { useSetupI18n } from "../../composables/useSetupI18n.js"
49
- import { useSetupLocale } from "../../composables/useSetupLocale.js"
50
- import { useShowDevOnlyKey } from "../../composables/useShowDevOnlyKey.js"
51
- import { theme as defaultTheme } from "../../theme.js"
52
- import { twMerge } from "../../utils/twMerge.js"
53
- import TestControls from "../TestControls/TestControls.vue"
54
-
55
- const $attrs = useDivideAttrs(["wrapper"])
56
-
57
- defineOptions({ name: "root", inheritAttrs: false, suspensible: false })
58
- const props = withDefaults(defineProps<{
59
- theme?: Theme
60
- outline?: boolean
61
- forceOutline?: boolean
62
- testWrapperMode?: boolean
63
- id?: string
64
- /** You can set a ref to the root element by passing :getRef="_ => el = _" */
65
- getRef?: (el: HTMLElement | null) => void
66
- /** True by default, should be passed import.meta.client if using nuxt, or false when running server side. */
67
- isClientSide?: boolean
68
- useBuiltinTranslations?: boolean
69
- }>(), {
70
- theme: undefined,
71
- testWrapperMode: false,
72
- outline: true,
73
- forceOutline: false,
74
- id: "app",
75
- getRef: undefined,
76
- isClientSide: true,
77
- useBuiltinTranslations: true
78
- })
79
-
80
- const el = ref<HTMLElement | null>(null)
81
-
82
- function handleRef(_: Element | ComponentPublicInstance | null): void {
83
- if (_ !== null && !(_ instanceof HTMLElement)) unreachable()
84
- el.value = _
85
- props.getRef?.(_)
43
+ <script setup>
44
+ import { unreachable } from "@alanscodelog/utils/unreachable.js";
45
+ import {} from "metamorphosis";
46
+ import { computed, onBeforeUnmount, onMounted, ref, toRaw } from "vue";
47
+ import { useAccesibilityOutline } from "../../composables/useAccesibilityOutline.js";
48
+ import { useDivideAttrs } from "../../composables/useDivideAttrs.js";
49
+ import { useNotificationHandler } from "../../composables/useNotificationHandler.js";
50
+ import { useSetupDarkMode } from "../../composables/useSetupDarkMode.js";
51
+ import { useSetupI18n } from "../../composables/useSetupI18n.js";
52
+ import { useSetupLocale } from "../../composables/useSetupLocale.js";
53
+ import { useShowDevOnlyKey } from "../../composables/useShowDevOnlyKey.js";
54
+ import { NotificationHandler } from "../../helpers/NotificationHandler.js";
55
+ import { theme as defaultTheme } from "../../theme.js";
56
+ import { twMerge } from "../../utils/twMerge.js";
57
+ import Notifications from "../LibNotifications/LibNotifications.vue";
58
+ import TestControls from "../TestControls/TestControls.vue";
59
+ const $attrs = useDivideAttrs(["wrapper"]);
60
+ defineOptions({ name: "root", inheritAttrs: false, suspensible: false });
61
+ const props = defineProps({
62
+ theme: { type: Object, required: false, default: void 0 },
63
+ outline: { type: Boolean, required: false, default: true },
64
+ forceOutline: { type: Boolean, required: false, default: false },
65
+ testWrapperMode: { type: Boolean, required: false, default: false },
66
+ id: { type: String, required: false, default: "app" },
67
+ getRef: { type: Function, required: false, default: void 0 },
68
+ isClientSide: { type: Boolean, required: false, default: true },
69
+ useBuiltinTranslations: { type: Boolean, required: false, default: true },
70
+ useNotifications: { type: Boolean, required: false, default: true },
71
+ notificationHandler: { type: Object, required: false, default: void 0 }
72
+ });
73
+ const el = ref(null);
74
+ function handleRef(_) {
75
+ if (_ !== null && !(_ instanceof HTMLElement)) unreachable();
76
+ el.value = _;
77
+ props.getRef?.(_);
86
78
  }
87
-
88
- const autoOutline = useAccesibilityOutline(el).outline
89
-
90
- const showOutline = computed(() => (props.outline && autoOutline.value) || props.forceOutline)
91
-
92
- const theme = computed(() => props.theme ?? defaultTheme)
93
- const themeCb = (): void => {
94
- toRaw(theme.value).attach(el.value!)
79
+ if (props.useNotifications) {
80
+ const handler = props.notificationHandler ?? new NotificationHandler();
81
+ useNotificationHandler(handler, props.isClientSide);
95
82
  }
83
+ const autoOutline = useAccesibilityOutline(el).outline;
84
+ const showOutline = computed(() => props.outline && autoOutline.value || props.forceOutline);
85
+ const theme = computed(() => props.theme ?? defaultTheme);
86
+ const themeCb = () => {
87
+ toRaw(theme.value).attach(el.value);
88
+ };
96
89
  if (props.isClientSide) {
97
- onMounted(() => {
98
- toRaw(theme.value).on("change", themeCb)
99
- themeCb()
100
- })
101
- onBeforeUnmount(() => {
102
- toRaw(theme.value).off("change", themeCb)
103
- })
90
+ onMounted(() => {
91
+ toRaw(theme.value).on("change", themeCb);
92
+ themeCb();
93
+ });
94
+ onBeforeUnmount(() => {
95
+ toRaw(theme.value).off("change", themeCb);
96
+ });
104
97
  }
105
-
106
- const darkModeSetup = useSetupDarkMode({ isClientSide: props.isClientSide })
107
-
108
- const darkMode = darkModeSetup.darkMode
109
-
110
- useShowDevOnlyKey()
111
-
98
+ const darkModeSetup = useSetupDarkMode({ isClientSide: props.isClientSide });
99
+ const darkMode = darkModeSetup.darkMode;
100
+ useShowDevOnlyKey();
112
101
  defineExpose({
113
- darkMode: darkModeSetup,
114
- })
115
-
102
+ darkMode: darkModeSetup
103
+ });
116
104
  if (props.useBuiltinTranslations) {
117
- const { languageLocale } = useSetupLocale()
118
- void useSetupI18n({
119
- locale: languageLocale,
120
- useBuiltinTranslations: true,
121
- useDummyMessageSetWhileLoading: true,
122
- })
105
+ const { languageLocale } = useSetupLocale();
106
+ void useSetupI18n({
107
+ locale: languageLocale,
108
+ useBuiltinTranslations: true,
109
+ useDummyMessageSetWhileLoading: true
110
+ });
123
111
  }
124
-
125
112
  </script>
126
-