@rotki/ui-library 3.0.0-beta.5 → 3.1.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 (163) hide show
  1. package/dist/components/accordions/accordion/RuiAccordion.js.map +1 -1
  2. package/dist/components/accordions/accordion/RuiAccordion.vue_vue_type_script_setup_true_lang.js +13 -2
  3. package/dist/components/accordions/accordion/RuiAccordion.vue_vue_type_script_setup_true_lang.js.map +1 -1
  4. package/dist/components/alerts/RuiAlert.vue.d.ts +2 -2
  5. package/dist/components/buttons/button/RuiButton.js.map +1 -1
  6. package/dist/components/buttons/button/RuiButton.vue.d.ts +7 -1
  7. package/dist/components/buttons/button/RuiButton.vue_vue_type_script_setup_true_lang.js +4 -2
  8. package/dist/components/buttons/button/RuiButton.vue_vue_type_script_setup_true_lang.js.map +1 -1
  9. package/dist/components/buttons/button/button-props.d.ts +3 -0
  10. package/dist/components/buttons/button/button-props.js +2 -1
  11. package/dist/components/buttons/button/button-props.js.map +1 -1
  12. package/dist/components/buttons/button/button-styles.d.ts +75 -0
  13. package/dist/components/buttons/button/button-styles.js +135 -4
  14. package/dist/components/buttons/button/button-styles.js.map +1 -1
  15. package/dist/components/cards/RuiCard.js.map +1 -1
  16. package/dist/components/cards/RuiCard.vue.d.ts +6 -0
  17. package/dist/components/cards/RuiCard.vue_vue_type_script_setup_true_lang.js +14 -2
  18. package/dist/components/cards/RuiCard.vue_vue_type_script_setup_true_lang.js.map +1 -1
  19. package/dist/components/chips/RuiChip.js.map +1 -1
  20. package/dist/components/chips/RuiChip.vue_vue_type_script_setup_true_lang.js +14 -0
  21. package/dist/components/chips/RuiChip.vue_vue_type_script_setup_true_lang.js.map +1 -1
  22. package/dist/components/chips/chip-props.d.ts +2 -0
  23. package/dist/components/chips/chip-props.js +3 -0
  24. package/dist/components/chips/chip-props.js.map +1 -1
  25. package/dist/components/color-picker/RuiColorInput.js.map +1 -1
  26. package/dist/components/color-picker/RuiColorInput.vue_vue_type_script_setup_true_lang.js +2 -2
  27. package/dist/components/color-picker/RuiColorInput.vue_vue_type_script_setup_true_lang.js.map +1 -1
  28. package/dist/components/date-time-picker/RuiDateTimePicker.js.map +1 -1
  29. package/dist/components/date-time-picker/RuiDateTimePicker.vue.d.ts +4 -0
  30. package/dist/components/date-time-picker/RuiDateTimePicker.vue_vue_type_script_setup_true_lang.js +6 -2
  31. package/dist/components/date-time-picker/RuiDateTimePicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
  32. package/dist/components/date-time-picker/RuiDateTimePickerMenu.js.map +1 -1
  33. package/dist/components/date-time-picker/RuiDateTimePickerMenu.vue_vue_type_script_setup_true_lang.js +1 -1
  34. package/dist/components/date-time-picker/RuiDateTimePickerMenu.vue_vue_type_script_setup_true_lang.js.map +1 -1
  35. package/dist/components/date-time-picker/RuiTimezoneSelect.js.map +1 -1
  36. package/dist/components/date-time-picker/RuiTimezoneSelect.vue.d.ts +4 -0
  37. package/dist/components/date-time-picker/RuiTimezoneSelect.vue_vue_type_script_setup_true_lang.js +3 -2
  38. package/dist/components/date-time-picker/RuiTimezoneSelect.vue_vue_type_script_setup_true_lang.js.map +1 -1
  39. package/dist/components/forms/auto-complete/RuiAutoComplete.js.map +1 -1
  40. package/dist/components/forms/auto-complete/RuiAutoComplete.vue_vue_type_script_setup_true_lang.js +6 -2
  41. package/dist/components/forms/auto-complete/RuiAutoComplete.vue_vue_type_script_setup_true_lang.js.map +1 -1
  42. package/dist/components/forms/auto-complete/RuiAutoCompleteSelection.js.map +1 -1
  43. package/dist/components/forms/auto-complete/RuiAutoCompleteSelection.vue_vue_type_script_setup_true_lang.js +9 -6
  44. package/dist/components/forms/auto-complete/RuiAutoCompleteSelection.vue_vue_type_script_setup_true_lang.js.map +1 -1
  45. package/dist/components/forms/auto-complete/auto-complete-props.d.ts +4 -0
  46. package/dist/components/forms/category-picker/RuiCategoryPicker.js.map +1 -1
  47. package/dist/components/forms/category-picker/RuiCategoryPicker.vue.d.ts +4 -1
  48. package/dist/components/forms/category-picker/RuiCategoryPicker.vue_vue_type_script_setup_true_lang.js +7 -4
  49. package/dist/components/forms/category-picker/RuiCategoryPicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
  50. package/dist/components/forms/check-control-styles.d.ts +27 -0
  51. package/dist/components/forms/check-control-styles.js +26 -1
  52. package/dist/components/forms/check-control-styles.js.map +1 -1
  53. package/dist/components/forms/checkbox/RuiCheckbox.js.map +1 -1
  54. package/dist/components/forms/checkbox/RuiCheckbox.vue.d.ts +6 -0
  55. package/dist/components/forms/checkbox/RuiCheckbox.vue_vue_type_script_setup_true_lang.js +14 -4
  56. package/dist/components/forms/checkbox/RuiCheckbox.vue_vue_type_script_setup_true_lang.js.map +1 -1
  57. package/dist/components/forms/checkbox/checkbox-group/RuiCheckboxGroup.js.map +1 -1
  58. package/dist/components/forms/checkbox/checkbox-group/RuiCheckboxGroup.vue.d.ts +4 -0
  59. package/dist/components/forms/checkbox/checkbox-group/RuiCheckboxGroup.vue_vue_type_script_setup_true_lang.js +7 -2
  60. package/dist/components/forms/checkbox/checkbox-group/RuiCheckboxGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
  61. package/dist/components/forms/field-defaults/RuiFieldDefaults.js.map +1 -1
  62. package/dist/components/forms/field-defaults/RuiFieldDefaults.vue.d.ts +3 -0
  63. package/dist/components/forms/field-defaults/RuiFieldDefaults.vue_vue_type_script_setup_true_lang.js +8 -2
  64. package/dist/components/forms/field-defaults/RuiFieldDefaults.vue_vue_type_script_setup_true_lang.js.map +1 -1
  65. package/dist/components/forms/file-upload/RuiFileUpload.js.map +1 -1
  66. package/dist/components/forms/file-upload/RuiFileUpload.vue.d.ts +4 -1
  67. package/dist/components/forms/file-upload/RuiFileUpload.vue_vue_type_script_setup_true_lang.js +10 -3
  68. package/dist/components/forms/file-upload/RuiFileUpload.vue_vue_type_script_setup_true_lang.js.map +1 -1
  69. package/dist/components/forms/radio-button/radio/RuiRadio.js.map +1 -1
  70. package/dist/components/forms/radio-button/radio/RuiRadio.vue.d.ts +6 -0
  71. package/dist/components/forms/radio-button/radio/RuiRadio.vue_vue_type_script_setup_true_lang.js +14 -3
  72. package/dist/components/forms/radio-button/radio/RuiRadio.vue_vue_type_script_setup_true_lang.js.map +1 -1
  73. package/dist/components/forms/radio-button/radio-group/RuiRadioGroup.js.map +1 -1
  74. package/dist/components/forms/radio-button/radio-group/RuiRadioGroup.vue.d.ts +4 -0
  75. package/dist/components/forms/radio-button/radio-group/RuiRadioGroup.vue_vue_type_script_setup_true_lang.js +7 -2
  76. package/dist/components/forms/radio-button/radio-group/RuiRadioGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
  77. package/dist/components/forms/revealable-text-field/RuiRevealableTextField.js.map +1 -1
  78. package/dist/components/forms/revealable-text-field/RuiRevealableTextField.vue_vue_type_script_setup_true_lang.js +3 -2
  79. package/dist/components/forms/revealable-text-field/RuiRevealableTextField.vue_vue_type_script_setup_true_lang.js.map +1 -1
  80. package/dist/components/forms/select/RuiMenuSelect.js.map +1 -1
  81. package/dist/components/forms/select/RuiMenuSelect.vue.d.ts +4 -0
  82. package/dist/components/forms/select/RuiMenuSelect.vue_vue_type_script_setup_true_lang.js +6 -2
  83. package/dist/components/forms/select/RuiMenuSelect.vue_vue_type_script_setup_true_lang.js.map +1 -1
  84. package/dist/components/forms/slider/RuiSlider.js.map +1 -1
  85. package/dist/components/forms/slider/RuiSlider.vue.d.ts +4 -0
  86. package/dist/components/forms/slider/RuiSlider.vue_vue_type_script_setup_true_lang.js +6 -3
  87. package/dist/components/forms/slider/RuiSlider.vue_vue_type_script_setup_true_lang.js.map +1 -1
  88. package/dist/components/forms/switch/RuiSwitch.js.map +1 -1
  89. package/dist/components/forms/switch/RuiSwitch.vue.d.ts +6 -0
  90. package/dist/components/forms/switch/RuiSwitch.vue_vue_type_script_setup_true_lang.js +25 -5
  91. package/dist/components/forms/switch/RuiSwitch.vue_vue_type_script_setup_true_lang.js.map +1 -1
  92. package/dist/components/forms/text-area/RuiTextArea.js.map +1 -1
  93. package/dist/components/forms/text-area/RuiTextArea.vue.d.ts +4 -0
  94. package/dist/components/forms/text-area/RuiTextArea.vue_vue_type_script_setup_true_lang.js +6 -4
  95. package/dist/components/forms/text-area/RuiTextArea.vue_vue_type_script_setup_true_lang.js.map +1 -1
  96. package/dist/components/forms/text-area/text-area-styles.d.ts +0 -1
  97. package/dist/components/forms/text-area/text-area-styles.js +0 -1
  98. package/dist/components/forms/text-area/text-area-styles.js.map +1 -1
  99. package/dist/components/forms/text-field/RuiTextField.js.map +1 -1
  100. package/dist/components/forms/text-field/RuiTextField.vue.d.ts +6 -2
  101. package/dist/components/forms/text-field/RuiTextField.vue_vue_type_script_setup_true_lang.js +6 -4
  102. package/dist/components/forms/text-field/RuiTextField.vue_vue_type_script_setup_true_lang.js.map +1 -1
  103. package/dist/components/forms/text-field/text-field-styles.d.ts +0 -1
  104. package/dist/components/forms/text-field/text-field-styles.js +0 -1
  105. package/dist/components/forms/text-field/text-field-styles.js.map +1 -1
  106. package/dist/components/helpers/RuiFormTextDetail.js.map +1 -1
  107. package/dist/components/helpers/RuiFormTextDetail.vue.d.ts +14 -0
  108. package/dist/components/helpers/RuiFormTextDetail.vue_vue_type_script_setup_true_lang.js +41 -11
  109. package/dist/components/helpers/RuiFormTextDetail.vue_vue_type_script_setup_true_lang.js.map +1 -1
  110. package/dist/components/loaders/RuiSkeletonBase.js.map +1 -1
  111. package/dist/components/loaders/RuiSkeletonBase.vue_vue_type_script_setup_true_lang.js.map +1 -1
  112. package/dist/components/overlays/menu/RuiMenu.js.map +1 -1
  113. package/dist/components/overlays/menu/RuiMenu.vue.d.ts +3 -0
  114. package/dist/components/overlays/menu/RuiMenu.vue_vue_type_script_setup_true_lang.js +9 -1
  115. package/dist/components/overlays/menu/RuiMenu.vue_vue_type_script_setup_true_lang.js.map +1 -1
  116. package/dist/components/tables/RuiDataTable.js.map +1 -1
  117. package/dist/components/tables/RuiDataTable.vue.d.ts +9 -0
  118. package/dist/components/tables/RuiDataTable.vue_vue_type_script_setup_true_lang.js +19 -7
  119. package/dist/components/tables/RuiDataTable.vue_vue_type_script_setup_true_lang.js.map +1 -1
  120. package/dist/components/tables/RuiExpandButton.js.map +1 -1
  121. package/dist/components/tables/RuiExpandButton.vue_vue_type_script_setup_true_lang.js.map +1 -1
  122. package/dist/components/tables/RuiTableHead.js.map +1 -1
  123. package/dist/components/tables/RuiTableHead.vue_vue_type_script_setup_true_lang.js +1 -1
  124. package/dist/components/tables/RuiTableHead.vue_vue_type_script_setup_true_lang.js.map +1 -1
  125. package/dist/components/tables/RuiTablePagination.js.map +1 -1
  126. package/dist/components/tables/RuiTablePagination.vue_vue_type_script_setup_true_lang.js +3 -3
  127. package/dist/components/tables/RuiTablePagination.vue_vue_type_script_setup_true_lang.js.map +1 -1
  128. package/dist/components/tables/data-table/RuiDataTableAppendRow.js.map +1 -1
  129. package/dist/components/tables/data-table/RuiDataTableAppendRow.vue_vue_type_script_setup_true_lang.js.map +1 -1
  130. package/dist/components/tables/data-table/RuiDataTableBody.js.map +1 -1
  131. package/dist/components/tables/data-table/RuiDataTableBody.vue_vue_type_script_setup_true_lang.js +4 -3
  132. package/dist/components/tables/data-table/RuiDataTableBody.vue_vue_type_script_setup_true_lang.js.map +1 -1
  133. package/dist/components/tables/data-table/RuiDataTableRow.js.map +1 -1
  134. package/dist/components/tables/data-table/RuiDataTableRow.vue_vue_type_script_setup_true_lang.js +4 -4
  135. package/dist/components/tables/data-table/RuiDataTableRow.vue_vue_type_script_setup_true_lang.js.map +1 -1
  136. package/dist/components/tables/data-table-styles.d.ts +6 -0
  137. package/dist/components/tables/data-table-styles.js +15 -7
  138. package/dist/components/tables/data-table-styles.js.map +1 -1
  139. package/dist/components/tabs/tab-items/RuiTabItems.js.map +1 -1
  140. package/dist/components/tabs/tab-items/RuiTabItems.vue_vue_type_script_setup_true_lang.js +9 -2
  141. package/dist/components/tabs/tab-items/RuiTabItems.vue_vue_type_script_setup_true_lang.js.map +1 -1
  142. package/dist/composables/clip-while-resizing.d.ts +15 -0
  143. package/dist/composables/clip-while-resizing.js +46 -0
  144. package/dist/composables/clip-while-resizing.js.map +1 -0
  145. package/dist/composables/defaults/field.d.ts +19 -3
  146. package/dist/composables/defaults/field.js +32 -6
  147. package/dist/composables/defaults/field.js.map +1 -1
  148. package/dist/composables/sticky-blocker.d.ts +20 -0
  149. package/dist/composables/sticky-blocker.js +62 -0
  150. package/dist/composables/sticky-blocker.js.map +1 -0
  151. package/dist/composables/tables/data-table/page-scroll.js +11 -1
  152. package/dist/composables/tables/data-table/page-scroll.js.map +1 -1
  153. package/dist/index.d.ts +6 -2
  154. package/dist/index.js.map +1 -1
  155. package/dist/style.css +352 -11
  156. package/dist/utils/development.d.ts +6 -0
  157. package/dist/utils/development.js +17 -0
  158. package/dist/utils/development.js.map +1 -0
  159. package/dist/utils/form-text-detail.d.ts +15 -0
  160. package/dist/utils/form-text-detail.js +11 -1
  161. package/dist/utils/form-text-detail.js.map +1 -1
  162. package/dist/web-types.json +242 -3
  163. package/package.json +1 -1
@@ -1,7 +1,7 @@
1
1
  import { get, set } from "../../../vendor/@vueuse/shared/dist/index.js";
2
2
  import { useElementBounding, useEventListener } from "../../../vendor/@vueuse/core/dist/index.js";
3
3
  import { cn } from "../../../utils/tv.js";
4
- import { useFormTextDetail } from "../../../utils/form-text-detail.js";
4
+ import { useFormDetails, useFormTextDetail } from "../../../utils/form-text-detail.js";
5
5
  import RuiFormTextDetail_default from "../../helpers/RuiFormTextDetail.js";
6
6
  import RuiFieldLabel_default from "../field-label/RuiFieldLabel.js";
7
7
  import { getNonRootAttrs, getRootAttrs } from "../../../utils/helpers.js";
@@ -55,6 +55,7 @@ var RuiSlider_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ define
55
55
  hint: { default: "" },
56
56
  errorMessages: { default: () => [] },
57
57
  successMessages: { default: () => [] },
58
+ details: { default: () => void 0 },
58
59
  hideDetails: {
59
60
  type: Boolean,
60
61
  default: false
@@ -78,6 +79,7 @@ var RuiSlider_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ define
78
79
  const generatedId = useId();
79
80
  const attrs = useAttrs();
80
81
  const { hasError } = useFormTextDetail(() => __props.errorMessages, () => __props.successMessages);
82
+ const detailsMode = useFormDetails(() => __props.details, () => __props.hideDetails);
81
83
  const inputId = computed(() => {
82
84
  const id = attrs.id;
83
85
  return typeof id === "string" && id ? id : generatedId;
@@ -234,13 +236,14 @@ var RuiSlider_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ define
234
236
  "data-id": "slider-thumb-label"
235
237
  }, toDisplayString(modelValue.value), 7)) : createCommentVNode("", true)
236
238
  ], 2)], 2)], 6)], 2)], 10, _hoisted_1),
237
- !__props.hideDetails ? (openBlock(), createBlock(RuiFormTextDetail_default, {
239
+ unref(detailsMode) !== "hidden" ? (openBlock(), createBlock(RuiFormTextDetail_default, {
238
240
  key: 1,
239
- class: "pt-1",
241
+ details: unref(detailsMode),
240
242
  "error-messages": __props.errorMessages,
241
243
  "success-messages": __props.successMessages,
242
244
  hint: __props.hint
243
245
  }, null, 8, [
246
+ "details",
244
247
  "error-messages",
245
248
  "success-messages",
246
249
  "hint"
@@ -1 +1 @@
1
- {"version":3,"file":"RuiSlider.vue_vue_type_script_setup_true_lang.js","names":["$attrs","_useModel","_openBlock","_createElementBlock","_mergeProps","_unref","_createBlock","RuiFieldLabel","_normalizeClass","_createCommentVNode","_createElementVNode","_normalizeStyle","_withDirectives","_vModelText","RuiSliderTicks","_toDisplayString","RuiFormTextDetail"],"sources":["../../../../src/components/forms/slider/RuiSlider.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { ContextColorsType } from '@/consts/colors';\nimport type { VueClassValue } from '@/types/class-value';\nimport RuiFieldLabel from '@/components/forms/field-label/RuiFieldLabel.vue';\nimport RuiSliderTicks from '@/components/forms/slider/RuiSliderTicks.vue';\nimport { HIGHLIGHT_COLOR_MAP, HIGHLIGHT_DEFAULT, SliderInteraction, sliderStyles } from '@/components/forms/slider/slider-styles';\nimport RuiFormTextDetail from '@/components/helpers/RuiFormTextDetail.vue';\nimport { useFormTextDetail } from '@/utils/form-text-detail';\nimport { getNonRootAttrs, getRootAttrs } from '@/utils/helpers';\nimport { cn } from '@/utils/tv';\n\nexport interface RuiSliderClassNames {\n root?: VueClassValue;\n slider?: VueClassValue;\n tick?: VueClassValue;\n}\n\nexport interface Props {\n min?: number;\n max?: number;\n step?: number;\n disabled?: boolean;\n showThumbLabel?: boolean;\n showTicks?: boolean;\n hideTrack?: boolean;\n tickSize?: number;\n vertical?: boolean;\n color?: ContextColorsType;\n label?: string;\n hint?: string;\n errorMessages?: string | string[];\n successMessages?: string | string[];\n hideDetails?: boolean;\n classNames?: RuiSliderClassNames;\n required?: boolean;\n}\n\ndefineOptions({\n name: 'RuiSlider',\n inheritAttrs: false,\n});\n\nconst modelValue = defineModel<number>({ default: 0 });\n\nconst {\n min = 0,\n max = 100,\n step = 1,\n disabled = false,\n showThumbLabel = false,\n showTicks = false,\n hideTrack = false,\n vertical = false,\n tickSize = 2,\n color = 'primary',\n label = '',\n hint = '',\n errorMessages = [],\n successMessages = [],\n hideDetails = false,\n classNames,\n required = false,\n} = defineProps<Props>();\n\nconst BIG_TICK_THRESHOLD = 4;\n\nconst isHovered = ref<boolean>(false);\nconst isFocused = ref<boolean>(false);\nconst isActive = ref<boolean>(false);\n\nconst outer = useTemplateRef<HTMLDivElement>('outer');\n\nconst generatedId = useId();\nconst attrs = useAttrs();\n\nconst { hasError } = useFormTextDetail(\n () => errorMessages,\n () => successMessages,\n);\n\n// the label above points at the range input, keeping a consumer's own id\nconst inputId = computed<string>(() => {\n const id = attrs.id;\n return typeof id === 'string' && id ? id : generatedId;\n});\n\nconst { width, height } = useElementBounding(outer);\n\nconst bigTick = computed<boolean>(() => tickSize > BIG_TICK_THRESHOLD);\n\nuseEventListener(document, 'mouseup', () => set(isActive, false));\n\nconst interaction = computed<SliderInteraction>(() => {\n if (disabled)\n return SliderInteraction.idle;\n if (get(isActive))\n return SliderInteraction.active;\n if (get(isFocused))\n return SliderInteraction.focus;\n if (get(isHovered))\n return SliderInteraction.hover;\n return SliderInteraction.idle;\n});\n\n// Layout ui: stable props only (not interaction), used for wrapper/label/outer/inner/input\nconst ui = computed<ReturnType<typeof sliderStyles>>(() => sliderStyles({\n disabled,\n vertical,\n color,\n bigTick: get(bigTick),\n hasLabel: !!label,\n}));\n\n// Track ui: includes interaction state, used for slider/thumb/ticks (changes on hover/focus/active)\nconst trackUi = computed<ReturnType<typeof sliderStyles>>(() => sliderStyles({\n disabled,\n vertical,\n interaction: get(interaction),\n color,\n bigTick: get(bigTick),\n}));\n\nconst totalTicks = computed<number>(() => (max - min) / step);\n\nconst currentTick = computed<number>(() => Math.round((get(modelValue) - min) / step));\n\nconst trackWidth = computed<string>(() => {\n const percentage = Math.min(100, Math.max(0, Math.round((get(currentTick) / get(totalTicks)) * 100)));\n return `${percentage}%`;\n});\n\nconst innerStyle = computed<Record<string, string>>(() => {\n const w = `${get(width)}px`;\n const h = `${get(height)}px`;\n const style: Record<string, string> = { width: vertical ? h : w, height: vertical ? w : h };\n if (vertical) {\n style['transform-origin'] = '0 0';\n style['--rui-slider-shift'] = h;\n }\n return style;\n});\n\nconst tickSizePx = computed<string>(() => `${tickSize}px`);\n\nconst ticksStyle = computed<Record<string, string>>(() => {\n const size = get(tickSizePx);\n return { margin: `0 calc(${size} / -2)`, width: `calc(100% + ${size})` };\n});\n\nconst tickStyle = computed<Record<string, string>>(() => {\n const size = get(tickSizePx);\n return { width: size, height: size };\n});\n\nconst highlightClass = computed<string>(() => get(bigTick) ? HIGHLIGHT_COLOR_MAP[color] : HIGHLIGHT_DEFAULT);\n\nconst tickClassOverride = computed<string | undefined>(() => cn(classNames?.tick));\n\nfunction isHighlightedTick(index: number): boolean {\n return index <= get(currentTick);\n}\n</script>\n\n<template>\n <div\n v-bind=\"getRootAttrs($attrs)\"\n :class=\"ui.root()\"\n >\n <!-- above the rail like any field's label, neutral in every state; the messages below carry the validation -->\n <RuiFieldLabel\n v-if=\"label\"\n :text=\"label\"\n :for=\"inputId\"\n :required=\"required\"\n :disabled=\"disabled\"\n :class=\"ui.label()\"\n />\n <div\n :class=\"ui.wrapper()\"\n :data-error=\"hasError ? '' : undefined\"\n data-id=\"slider-wrapper\"\n >\n <div\n ref=\"outer\"\n :class=\"ui.outer()\"\n >\n <div\n :class=\"ui.inner()\"\n :style=\"innerStyle\"\n >\n <input\n :id=\"inputId\"\n v-model.number=\"modelValue\"\n :class=\"ui.input()\"\n type=\"range\"\n :max=\"max\"\n :min=\"min\"\n :step=\"step\"\n :disabled=\"disabled\"\n :aria-invalid=\"hasError\"\n :aria-label=\"label || undefined\"\n :aria-valuetext=\"String(modelValue)\"\n v-bind=\"getNonRootAttrs($attrs, ['class', 'id'])\"\n @mouseenter=\"isHovered = true\"\n @mouseleave=\"isHovered = false\"\n @focus=\"isFocused = true\"\n @blur=\"isFocused = false\"\n @mousedown=\"isActive = true\"\n @mouseup=\"isActive = false\"\n />\n <div :class=\"trackUi.slider()\">\n <div :class=\"trackUi.sliderInner()\">\n <div :class=\"trackUi.container({ class: cn(classNames?.slider) })\">\n <div\n v-if=\"!hideTrack\"\n :class=\"trackUi.track()\"\n :style=\"{ width: trackWidth }\"\n data-id=\"slider-track\"\n />\n <RuiSliderTicks\n v-if=\"showTicks && !disabled\"\n :count=\"totalTicks\"\n :container-class=\"trackUi.ticks()\"\n :container-style=\"ticksStyle\"\n :tick-class=\"trackUi.tick()\"\n :tick-style=\"tickStyle\"\n :hide-track=\"hideTrack\"\n :highlight-class=\"highlightClass\"\n :tick-class-override=\"tickClassOverride\"\n :is-highlighted=\"isHighlightedTick\"\n />\n </div>\n <div\n :class=\"trackUi.thumb()\"\n :style=\"{ left: trackWidth }\"\n data-id=\"slider-thumb\"\n />\n <div\n v-if=\"showThumbLabel && !disabled\"\n :class=\"trackUi.thumbLabel()\"\n :style=\"{ left: trackWidth }\"\n data-id=\"slider-thumb-label\"\n >\n {{ modelValue }}\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n <RuiFormTextDetail\n v-if=\"!hideDetails\"\n class=\"pt-1\"\n :error-messages=\"errorMessages\"\n :success-messages=\"successMessages\"\n :hint=\"hint\"\n />\n </div>\n</template>\n"],"mappings":"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"}
1
+ {"version":3,"file":"RuiSlider.vue_vue_type_script_setup_true_lang.js","names":["$attrs","_useModel","_openBlock","_createElementBlock","_mergeProps","_unref","_createBlock","RuiFieldLabel","_normalizeClass","_createCommentVNode","_createElementVNode","_normalizeStyle","_withDirectives","_vModelText","RuiSliderTicks","_toDisplayString","RuiFormTextDetail"],"sources":["../../../../src/components/forms/slider/RuiSlider.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { ContextColorsType } from '@/consts/colors';\nimport type { VueClassValue } from '@/types/class-value';\nimport RuiFieldLabel from '@/components/forms/field-label/RuiFieldLabel.vue';\nimport RuiSliderTicks from '@/components/forms/slider/RuiSliderTicks.vue';\nimport { HIGHLIGHT_COLOR_MAP, HIGHLIGHT_DEFAULT, SliderInteraction, sliderStyles } from '@/components/forms/slider/slider-styles';\nimport RuiFormTextDetail from '@/components/helpers/RuiFormTextDetail.vue';\nimport { type FormDetails, useFormDetails, useFormTextDetail } from '@/utils/form-text-detail';\nimport { getNonRootAttrs, getRootAttrs } from '@/utils/helpers';\nimport { cn } from '@/utils/tv';\n\nexport interface RuiSliderClassNames {\n root?: VueClassValue;\n slider?: VueClassValue;\n tick?: VueClassValue;\n}\n\nexport interface Props {\n min?: number;\n max?: number;\n step?: number;\n disabled?: boolean;\n showThumbLabel?: boolean;\n showTicks?: boolean;\n hideTrack?: boolean;\n tickSize?: number;\n vertical?: boolean;\n color?: ContextColorsType;\n label?: string;\n hint?: string;\n errorMessages?: string | string[];\n successMessages?: string | string[];\n /** The line under the slider for its hint and messages: `reserve`, `auto` or `hidden`; falls back to the nearest `RuiFieldDefaults`, then the app default, then `reserve`. */\n details?: FormDetails;\n /** @deprecated Use `details=\"hidden\"`. Removed in 4.0. */\n hideDetails?: boolean;\n classNames?: RuiSliderClassNames;\n required?: boolean;\n}\n\ndefineOptions({\n name: 'RuiSlider',\n inheritAttrs: false,\n});\n\nconst modelValue = defineModel<number>({ default: 0 });\n\nconst {\n min = 0,\n max = 100,\n step = 1,\n disabled = false,\n showThumbLabel = false,\n showTicks = false,\n hideTrack = false,\n vertical = false,\n tickSize = 2,\n color = 'primary',\n label = '',\n hint = '',\n errorMessages = [],\n successMessages = [],\n details = undefined,\n hideDetails = false,\n classNames,\n required = false,\n} = defineProps<Props>();\n\nconst BIG_TICK_THRESHOLD = 4;\n\nconst isHovered = ref<boolean>(false);\nconst isFocused = ref<boolean>(false);\nconst isActive = ref<boolean>(false);\n\nconst outer = useTemplateRef<HTMLDivElement>('outer');\n\nconst generatedId = useId();\nconst attrs = useAttrs();\n\nconst { hasError } = useFormTextDetail(\n () => errorMessages,\n () => successMessages,\n);\nconst detailsMode = useFormDetails(() => details, () => hideDetails);\n\n// the label above points at the range input, keeping a consumer's own id\nconst inputId = computed<string>(() => {\n const id = attrs.id;\n return typeof id === 'string' && id ? id : generatedId;\n});\n\nconst { width, height } = useElementBounding(outer);\n\nconst bigTick = computed<boolean>(() => tickSize > BIG_TICK_THRESHOLD);\n\nuseEventListener(document, 'mouseup', () => set(isActive, false));\n\nconst interaction = computed<SliderInteraction>(() => {\n if (disabled)\n return SliderInteraction.idle;\n if (get(isActive))\n return SliderInteraction.active;\n if (get(isFocused))\n return SliderInteraction.focus;\n if (get(isHovered))\n return SliderInteraction.hover;\n return SliderInteraction.idle;\n});\n\n// Layout ui: stable props only (not interaction), used for wrapper/label/outer/inner/input\nconst ui = computed<ReturnType<typeof sliderStyles>>(() => sliderStyles({\n disabled,\n vertical,\n color,\n bigTick: get(bigTick),\n hasLabel: !!label,\n}));\n\n// Track ui: includes interaction state, used for slider/thumb/ticks (changes on hover/focus/active)\nconst trackUi = computed<ReturnType<typeof sliderStyles>>(() => sliderStyles({\n disabled,\n vertical,\n interaction: get(interaction),\n color,\n bigTick: get(bigTick),\n}));\n\nconst totalTicks = computed<number>(() => (max - min) / step);\n\nconst currentTick = computed<number>(() => Math.round((get(modelValue) - min) / step));\n\nconst trackWidth = computed<string>(() => {\n const percentage = Math.min(100, Math.max(0, Math.round((get(currentTick) / get(totalTicks)) * 100)));\n return `${percentage}%`;\n});\n\nconst innerStyle = computed<Record<string, string>>(() => {\n const w = `${get(width)}px`;\n const h = `${get(height)}px`;\n const style: Record<string, string> = { width: vertical ? h : w, height: vertical ? w : h };\n if (vertical) {\n style['transform-origin'] = '0 0';\n style['--rui-slider-shift'] = h;\n }\n return style;\n});\n\nconst tickSizePx = computed<string>(() => `${tickSize}px`);\n\nconst ticksStyle = computed<Record<string, string>>(() => {\n const size = get(tickSizePx);\n return { margin: `0 calc(${size} / -2)`, width: `calc(100% + ${size})` };\n});\n\nconst tickStyle = computed<Record<string, string>>(() => {\n const size = get(tickSizePx);\n return { width: size, height: size };\n});\n\nconst highlightClass = computed<string>(() => get(bigTick) ? HIGHLIGHT_COLOR_MAP[color] : HIGHLIGHT_DEFAULT);\n\nconst tickClassOverride = computed<string | undefined>(() => cn(classNames?.tick));\n\nfunction isHighlightedTick(index: number): boolean {\n return index <= get(currentTick);\n}\n</script>\n\n<template>\n <div\n v-bind=\"getRootAttrs($attrs)\"\n :class=\"ui.root()\"\n >\n <!-- above the rail like any field's label, neutral in every state; the messages below carry the validation -->\n <RuiFieldLabel\n v-if=\"label\"\n :text=\"label\"\n :for=\"inputId\"\n :required=\"required\"\n :disabled=\"disabled\"\n :class=\"ui.label()\"\n />\n <div\n :class=\"ui.wrapper()\"\n :data-error=\"hasError ? '' : undefined\"\n data-id=\"slider-wrapper\"\n >\n <div\n ref=\"outer\"\n :class=\"ui.outer()\"\n >\n <div\n :class=\"ui.inner()\"\n :style=\"innerStyle\"\n >\n <input\n :id=\"inputId\"\n v-model.number=\"modelValue\"\n :class=\"ui.input()\"\n type=\"range\"\n :max=\"max\"\n :min=\"min\"\n :step=\"step\"\n :disabled=\"disabled\"\n :aria-invalid=\"hasError\"\n :aria-label=\"label || undefined\"\n :aria-valuetext=\"String(modelValue)\"\n v-bind=\"getNonRootAttrs($attrs, ['class', 'id'])\"\n @mouseenter=\"isHovered = true\"\n @mouseleave=\"isHovered = false\"\n @focus=\"isFocused = true\"\n @blur=\"isFocused = false\"\n @mousedown=\"isActive = true\"\n @mouseup=\"isActive = false\"\n />\n <div :class=\"trackUi.slider()\">\n <div :class=\"trackUi.sliderInner()\">\n <div :class=\"trackUi.container({ class: cn(classNames?.slider) })\">\n <div\n v-if=\"!hideTrack\"\n :class=\"trackUi.track()\"\n :style=\"{ width: trackWidth }\"\n data-id=\"slider-track\"\n />\n <RuiSliderTicks\n v-if=\"showTicks && !disabled\"\n :count=\"totalTicks\"\n :container-class=\"trackUi.ticks()\"\n :container-style=\"ticksStyle\"\n :tick-class=\"trackUi.tick()\"\n :tick-style=\"tickStyle\"\n :hide-track=\"hideTrack\"\n :highlight-class=\"highlightClass\"\n :tick-class-override=\"tickClassOverride\"\n :is-highlighted=\"isHighlightedTick\"\n />\n </div>\n <div\n :class=\"trackUi.thumb()\"\n :style=\"{ left: trackWidth }\"\n data-id=\"slider-thumb\"\n />\n <div\n v-if=\"showThumbLabel && !disabled\"\n :class=\"trackUi.thumbLabel()\"\n :style=\"{ left: trackWidth }\"\n data-id=\"slider-thumb-label\"\n >\n {{ modelValue }}\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n <RuiFormTextDetail\n v-if=\"detailsMode !== 'hidden'\"\n :details=\"detailsMode\"\n :error-messages=\"errorMessages\"\n :success-messages=\"successMessages\"\n :hint=\"hint\"\n />\n </div>\n</template>\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"RuiSwitch.js","names":["_sfc_main"],"sources":["../../../../src/components/forms/switch/RuiSwitch.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport type { ContextColorsType } from '@/consts/colors';\nimport RuiFormTextDetail from '@/components/helpers/RuiFormTextDetail.vue';\nimport { useFormTextDetail } from '@/utils/form-text-detail';\nimport { getNonRootAttrs, getRootAttrs } from '@/utils/helpers';\nimport { tv } from '@/utils/tv';\n\nexport interface Props {\n disabled?: boolean;\n color?: ContextColorsType;\n size?: 'sm';\n label?: string;\n hint?: string;\n errorMessages?: string | string[];\n successMessages?: string | string[];\n hideDetails?: boolean;\n required?: boolean;\n}\n\ndefineOptions({\n name: 'RuiSwitch',\n inheritAttrs: false,\n});\n\nconst modelValue = defineModel<boolean>({ default: false });\n\nconst {\n disabled = false,\n color = undefined,\n size = undefined,\n label = '',\n hint = '',\n errorMessages = [],\n successMessages = [],\n hideDetails = false,\n required = false,\n} = defineProps<Props>();\n\ndefineSlots<{\n default?: () => any;\n}>();\n\nconst switchStyles = tv({\n slots: {\n // 13px to the label, the gap a checkbox or radio leaves, so the focus ring clears the text\n wrapper: 'relative flex gap-3.25 items-start cursor-pointer group/switch',\n // 40 × 22, nudged down a pixel to sit centred on the label's 24px line\n inner: 'relative w-10 h-5.5 mt-px shrink-0',\n // the off track is the control edge color, 3:1 against the page in both themes\n input: 'peer appearance-none relative w-full h-full rounded-full bg-rui-outline transition-colors duration-150 cursor-pointer focus-visible:focus-ring',\n toggle: [\n 'absolute size-4.5 transition-all duration-75 ease-in-out -translate-y-1/2 top-1/2 rounded-full pointer-events-none',\n 'bg-white left-0.5 shadow-rui-control',\n ].join(' '),\n label: 'text-rui-text text-sm/6',\n },\n variants: {\n checked: {\n true: {\n toggle: 'left-5',\n },\n false: {},\n },\n disabled: {\n true: {\n wrapper: 'cursor-not-allowed',\n input: 'bg-rui-neutral-200! dark:bg-rui-neutral-800! cursor-not-allowed',\n toggle: 'bg-rui-neutral-50! dark:bg-rui-neutral-600! shadow-none!',\n label: 'text-rui-text-disabled',\n },\n },\n size: {\n sm: {\n inner: 'w-8.5 h-4.5 mt-0.75',\n toggle: 'size-3.5',\n },\n },\n // a ring and the message below mark the state; a filled red or green track would read as \"on\"\n validation: {\n error: {\n input: 'ring-1 ring-rui-error',\n },\n success: {\n input: 'ring-1 ring-rui-success',\n },\n },\n color: {\n primary: {},\n secondary: {},\n error: {},\n warning: {},\n info: {},\n success: {},\n },\n },\n compoundVariants: [\n { checked: false, disabled: false, class: { input: 'group-hover/switch:bg-rui-neutral-500 dark:group-hover/switch:bg-rui-neutral-400' } },\n\n // Checked (no color): an inverted neutral track, with a dark knob in dark mode\n { checked: true, disabled: false, class: { input: 'bg-rui-neutral-900 dark:bg-rui-neutral-100', toggle: 'dark:bg-rui-neutral-900' } },\n\n // Checked + color: a solid track with the white knob, in both themes\n { checked: true, disabled: false, color: 'primary', class: { input: 'bg-rui-primary dark:bg-rui-primary', toggle: 'dark:bg-white' } },\n { checked: true, disabled: false, color: 'secondary', class: { input: 'bg-rui-secondary dark:bg-rui-secondary', toggle: 'dark:bg-white' } },\n // a status color's dark `main` is a text tone, so the track takes the deep `darker` under the white knob\n { checked: true, disabled: false, color: 'error', class: { input: 'bg-rui-error dark:bg-rui-error-darker', toggle: 'dark:bg-white' } },\n { checked: true, disabled: false, color: 'warning', class: { input: 'bg-rui-warning dark:bg-rui-warning-darker', toggle: 'dark:bg-white' } },\n { checked: true, disabled: false, color: 'info', class: { input: 'bg-rui-info dark:bg-rui-info-darker', toggle: 'dark:bg-white' } },\n { checked: true, disabled: false, color: 'success', class: { input: 'bg-rui-success dark:bg-rui-success-darker', toggle: 'dark:bg-white' } },\n\n // Size sm + checked: 34 - 14 - 2\n { size: 'sm', checked: true, class: { toggle: 'left-4.5' } },\n ],\n defaultVariants: {\n checked: false,\n disabled: false,\n },\n});\n\nconst { hasError, validation } = useFormTextDetail(\n () => errorMessages,\n () => successMessages,\n);\n\nconst ui = computed<ReturnType<typeof switchStyles>>(() => switchStyles({\n checked: get(modelValue),\n disabled,\n size,\n validation: get(validation),\n color,\n}));\n\nfunction input(event: Event): void {\n const target = event.target;\n if (target instanceof HTMLInputElement)\n set(modelValue, target.checked);\n}\n</script>\n\n<template>\n <div v-bind=\"getRootAttrs($attrs)\">\n <label\n :class=\"ui.wrapper()\"\n :data-disabled=\"disabled || undefined\"\n :data-checked=\"modelValue || undefined\"\n :data-error=\"hasError ? '' : undefined\"\n >\n <div :class=\"ui.inner()\">\n <input\n :checked=\"modelValue\"\n type=\"checkbox\"\n :class=\"ui.input()\"\n :disabled=\"disabled\"\n :aria-invalid=\"hasError\"\n v-bind=\"getNonRootAttrs($attrs)\"\n @input=\"input($event)\"\n />\n <div :class=\"ui.toggle()\" />\n </div>\n <span\n v-if=\"label || $slots.default\"\n :class=\"ui.label()\"\n >\n <slot>{{ label }}</slot>\n <span\n v-if=\"required\"\n class=\"text-rui-error\"\n >\n *\n </span>\n </span>\n </label>\n <RuiFormTextDetail\n v-if=\"!hideDetails\"\n class=\"pt-1\"\n :error-messages=\"errorMessages\"\n :success-messages=\"successMessages\"\n :hint=\"hint\"\n />\n </div>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"RuiSwitch.js","names":["_sfc_main"],"sources":["../../../../src/components/forms/switch/RuiSwitch.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport type { ContextColorsType } from '@/consts/colors';\nimport RuiFormTextDetail from '@/components/helpers/RuiFormTextDetail.vue';\nimport { type FormDetails, useFormDetails, useFormTextDetail } from '@/utils/form-text-detail';\nimport { getNonRootAttrs, getRootAttrs } from '@/utils/helpers';\nimport { tv } from '@/utils/tv';\n\nexport interface Props {\n disabled?: boolean;\n color?: ContextColorsType;\n size?: 'sm';\n label?: string;\n hint?: string;\n errorMessages?: string | string[];\n successMessages?: string | string[];\n /** The line under the control for its hint and messages: `reserve`, `auto` or `hidden`; falls back to the nearest `RuiFieldDefaults`, then the app default, then `reserve`. */\n details?: FormDetails;\n /** @deprecated Use `details=\"hidden\"`. Removed in 4.0. */\n hideDetails?: boolean;\n /** Puts the hint or message under the label text instead of under the track, so a list of switches keeps one text column. */\n detailsUnderLabel?: boolean;\n required?: boolean;\n}\n\ndefineOptions({\n name: 'RuiSwitch',\n inheritAttrs: false,\n});\n\nconst modelValue = defineModel<boolean>({ default: false });\n\nconst {\n disabled = false,\n color = undefined,\n size = undefined,\n label = '',\n hint = '',\n errorMessages = [],\n successMessages = [],\n details = undefined,\n hideDetails = false,\n detailsUnderLabel = false,\n required = false,\n} = defineProps<Props>();\n\ndefineSlots<{\n default?: () => any;\n}>();\n\nconst switchStyles = tv({\n slots: {\n // 13px to the label, the gap a checkbox or radio leaves, so the focus ring clears the text\n wrapper: 'relative flex gap-3.25 items-start cursor-pointer group/switch',\n // 40 × 22, nudged down a pixel to sit centred on the label's 24px line\n inner: 'relative w-10 h-5.5 mt-px shrink-0',\n // the off track is the control edge color, 3:1 against the page in both themes\n input: 'peer appearance-none relative w-full h-full rounded-full bg-rui-outline transition-colors duration-150 cursor-pointer focus-visible:focus-ring',\n toggle: [\n 'absolute size-4.5 transition-all duration-75 ease-in-out -translate-y-1/2 top-1/2 rounded-full pointer-events-none',\n 'bg-white left-0.5 shadow-rui-control',\n ].join(' '),\n label: 'text-rui-text text-sm/6',\n details: '',\n },\n variants: {\n // indented by the track and the 13px gap, so the message starts where the label does\n underLabel: {\n true: { details: 'pl-13.25' },\n false: {},\n },\n checked: {\n true: {\n toggle: 'left-5',\n },\n false: {},\n },\n disabled: {\n true: {\n wrapper: 'cursor-not-allowed',\n input: 'bg-rui-neutral-200! dark:bg-rui-neutral-800! cursor-not-allowed',\n toggle: 'bg-rui-neutral-50! dark:bg-rui-neutral-600! shadow-none!',\n label: 'text-rui-text-disabled',\n },\n },\n size: {\n sm: {\n inner: 'w-8.5 h-4.5 mt-0.75',\n toggle: 'size-3.5',\n },\n },\n // a ring and the message below mark the state; a filled red or green track would read as \"on\"\n validation: {\n error: {\n input: 'ring-1 ring-rui-error',\n },\n success: {\n input: 'ring-1 ring-rui-success',\n },\n },\n color: {\n primary: {},\n secondary: {},\n error: {},\n warning: {},\n info: {},\n success: {},\n },\n },\n compoundVariants: [\n { checked: false, disabled: false, class: { input: 'group-hover/switch:bg-rui-neutral-500 dark:group-hover/switch:bg-rui-neutral-400' } },\n\n // Checked (no color): an inverted neutral track, with a dark knob in dark mode\n { checked: true, disabled: false, class: { input: 'bg-rui-neutral-900 dark:bg-rui-neutral-100', toggle: 'dark:bg-rui-neutral-900' } },\n\n // Checked + color: a solid track with the white knob, in both themes\n { checked: true, disabled: false, color: 'primary', class: { input: 'bg-rui-primary dark:bg-rui-primary', toggle: 'dark:bg-white' } },\n { checked: true, disabled: false, color: 'secondary', class: { input: 'bg-rui-secondary dark:bg-rui-secondary', toggle: 'dark:bg-white' } },\n // a status color's dark `main` is a text tone, so the track takes the deep `darker` under the white knob\n { checked: true, disabled: false, color: 'error', class: { input: 'bg-rui-error dark:bg-rui-error-darker', toggle: 'dark:bg-white' } },\n { checked: true, disabled: false, color: 'warning', class: { input: 'bg-rui-warning dark:bg-rui-warning-darker', toggle: 'dark:bg-white' } },\n { checked: true, disabled: false, color: 'info', class: { input: 'bg-rui-info dark:bg-rui-info-darker', toggle: 'dark:bg-white' } },\n { checked: true, disabled: false, color: 'success', class: { input: 'bg-rui-success dark:bg-rui-success-darker', toggle: 'dark:bg-white' } },\n\n // Size sm + checked: 34 - 14 - 2\n { size: 'sm', checked: true, class: { toggle: 'left-4.5' } },\n // sm: a 34px track\n { size: 'sm', underLabel: true, class: { details: 'pl-11.75' } },\n ],\n defaultVariants: {\n checked: false,\n disabled: false,\n },\n});\n\nconst { hasError, validation } = useFormTextDetail(\n () => errorMessages,\n () => successMessages,\n);\nconst detailsMode = useFormDetails(() => details, () => hideDetails);\n\nconst ui = computed<ReturnType<typeof switchStyles>>(() => switchStyles({\n checked: get(modelValue),\n disabled,\n size,\n validation: get(validation),\n color,\n underLabel: detailsUnderLabel,\n}));\n\nfunction input(event: Event): void {\n const target = event.target;\n if (target instanceof HTMLInputElement)\n set(modelValue, target.checked);\n}\n</script>\n\n<template>\n <div v-bind=\"getRootAttrs($attrs)\">\n <label\n :class=\"ui.wrapper()\"\n :data-disabled=\"disabled || undefined\"\n :data-checked=\"modelValue || undefined\"\n :data-error=\"hasError ? '' : undefined\"\n >\n <div :class=\"ui.inner()\">\n <input\n :checked=\"modelValue\"\n type=\"checkbox\"\n :class=\"ui.input()\"\n :disabled=\"disabled\"\n :aria-invalid=\"hasError\"\n v-bind=\"getNonRootAttrs($attrs)\"\n @input=\"input($event)\"\n />\n <div :class=\"ui.toggle()\" />\n </div>\n <span\n v-if=\"label || $slots.default\"\n :class=\"ui.label()\"\n >\n <slot>{{ label }}</slot>\n <span\n v-if=\"required\"\n class=\"text-rui-error\"\n >\n *\n </span>\n </span>\n </label>\n <RuiFormTextDetail\n v-if=\"detailsMode !== 'hidden'\"\n :class=\"ui.details()\"\n :details=\"detailsMode\"\n :error-messages=\"errorMessages\"\n :success-messages=\"successMessages\"\n :hint=\"hint\"\n />\n </div>\n</template>\n"],"mappings":""}
@@ -1,4 +1,5 @@
1
1
  import type { ContextColorsType } from '../../../consts/colors.js';
2
+ import { type FormDetails } from '../../../utils/form-text-detail.js';
2
3
  export interface Props {
3
4
  disabled?: boolean;
4
5
  color?: ContextColorsType;
@@ -7,7 +8,12 @@ export interface Props {
7
8
  hint?: string;
8
9
  errorMessages?: string | string[];
9
10
  successMessages?: string | string[];
11
+ /** The line under the control for its hint and messages: `reserve`, `auto` or `hidden`; falls back to the nearest `RuiFieldDefaults`, then the app default, then `reserve`. */
12
+ details?: FormDetails;
13
+ /** @deprecated Use `details="hidden"`. Removed in 4.0. */
10
14
  hideDetails?: boolean;
15
+ /** Puts the hint or message under the label text instead of under the track, so a list of switches keeps one text column. */
16
+ detailsUnderLabel?: boolean;
11
17
  required?: boolean;
12
18
  }
13
19
  type __VLS_Props = Props;
@@ -1,6 +1,6 @@
1
1
  import { get, set } from "../../../vendor/@vueuse/shared/dist/index.js";
2
2
  import { tv } from "../../../utils/tv.js";
3
- import { useFormTextDetail } from "../../../utils/form-text-detail.js";
3
+ import { useFormDetails, useFormTextDetail } from "../../../utils/form-text-detail.js";
4
4
  import RuiFormTextDetail_default from "../../helpers/RuiFormTextDetail.js";
5
5
  import { getNonRootAttrs, getRootAttrs } from "../../../utils/helpers.js";
6
6
  import { computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, defineComponent, guardReactiveProps, mergeModels, mergeProps, normalizeClass, normalizeProps, openBlock, renderSlot, toDisplayString, unref, useModel } from "vue";
@@ -34,10 +34,15 @@ var RuiSwitch_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ define
34
34
  hint: { default: "" },
35
35
  errorMessages: { default: () => [] },
36
36
  successMessages: { default: () => [] },
37
+ details: { default: () => void 0 },
37
38
  hideDetails: {
38
39
  type: Boolean,
39
40
  default: false
40
41
  },
42
+ detailsUnderLabel: {
43
+ type: Boolean,
44
+ default: false
45
+ },
41
46
  required: {
42
47
  type: Boolean,
43
48
  default: false
@@ -58,9 +63,14 @@ var RuiSwitch_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ define
58
63
  inner: "relative w-10 h-5.5 mt-px shrink-0",
59
64
  input: "peer appearance-none relative w-full h-full rounded-full bg-rui-outline transition-colors duration-150 cursor-pointer focus-visible:focus-ring",
60
65
  toggle: ["absolute size-4.5 transition-all duration-75 ease-in-out -translate-y-1/2 top-1/2 rounded-full pointer-events-none", "bg-white left-0.5 shadow-rui-control"].join(" "),
61
- label: "text-rui-text text-sm/6"
66
+ label: "text-rui-text text-sm/6",
67
+ details: ""
62
68
  },
63
69
  variants: {
70
+ underLabel: {
71
+ true: { details: "pl-13.25" },
72
+ false: {}
73
+ },
64
74
  checked: {
65
75
  true: { toggle: "left-5" },
66
76
  false: {}
@@ -160,6 +170,11 @@ var RuiSwitch_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ define
160
170
  size: "sm",
161
171
  checked: true,
162
172
  class: { toggle: "left-4.5" }
173
+ },
174
+ {
175
+ size: "sm",
176
+ underLabel: true,
177
+ class: { details: "pl-11.75" }
163
178
  }
164
179
  ],
165
180
  defaultVariants: {
@@ -168,12 +183,14 @@ var RuiSwitch_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ define
168
183
  }
169
184
  });
170
185
  const { hasError, validation } = useFormTextDetail(() => __props.errorMessages, () => __props.successMessages);
186
+ const detailsMode = useFormDetails(() => __props.details, () => __props.hideDetails);
171
187
  const ui = computed(() => switchStyles({
172
188
  checked: get(modelValue),
173
189
  disabled: __props.disabled,
174
190
  size: __props.size,
175
191
  validation: get(validation),
176
- color: __props.color
192
+ color: __props.color,
193
+ underLabel: __props.detailsUnderLabel
177
194
  }));
178
195
  function input(event) {
179
196
  const target = event.target;
@@ -194,13 +211,16 @@ var RuiSwitch_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ define
194
211
  }, unref(getNonRootAttrs)(_ctx.$attrs), { onInput: _cache[0] || (_cache[0] = ($event) => input($event)) }), null, 16, _hoisted_2), createElementVNode("div", { class: normalizeClass(unref(ui).toggle()) }, null, 2)], 2), __props.label || _ctx.$slots.default ? (openBlock(), createElementBlock("span", {
195
212
  key: 0,
196
213
  class: normalizeClass(unref(ui).label())
197
- }, [renderSlot(_ctx.$slots, "default", {}, () => [createTextVNode(toDisplayString(__props.label), 1)]), __props.required ? (openBlock(), createElementBlock("span", _hoisted_3, " * ")) : createCommentVNode("", true)], 2)) : createCommentVNode("", true)], 10, _hoisted_1), !__props.hideDetails ? (openBlock(), createBlock(RuiFormTextDetail_default, {
214
+ }, [renderSlot(_ctx.$slots, "default", {}, () => [createTextVNode(toDisplayString(__props.label), 1)]), __props.required ? (openBlock(), createElementBlock("span", _hoisted_3, " * ")) : createCommentVNode("", true)], 2)) : createCommentVNode("", true)], 10, _hoisted_1), unref(detailsMode) !== "hidden" ? (openBlock(), createBlock(RuiFormTextDetail_default, {
198
215
  key: 0,
199
- class: "pt-1",
216
+ class: normalizeClass(unref(ui).details()),
217
+ details: unref(detailsMode),
200
218
  "error-messages": __props.errorMessages,
201
219
  "success-messages": __props.successMessages,
202
220
  hint: __props.hint
203
221
  }, null, 8, [
222
+ "class",
223
+ "details",
204
224
  "error-messages",
205
225
  "success-messages",
206
226
  "hint"
@@ -1 +1 @@
1
- {"version":3,"file":"RuiSwitch.vue_vue_type_script_setup_true_lang.js","names":["$attrs","$slots","_useModel","_openBlock","_createElementBlock","_normalizeProps","_guardReactiveProps","_unref","_createElementVNode","_normalizeClass","_mergeProps","_renderSlot","_createTextVNode","_toDisplayString","_createCommentVNode","_createBlock","RuiFormTextDetail"],"sources":["../../../../src/components/forms/switch/RuiSwitch.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport type { ContextColorsType } from '@/consts/colors';\nimport RuiFormTextDetail from '@/components/helpers/RuiFormTextDetail.vue';\nimport { useFormTextDetail } from '@/utils/form-text-detail';\nimport { getNonRootAttrs, getRootAttrs } from '@/utils/helpers';\nimport { tv } from '@/utils/tv';\n\nexport interface Props {\n disabled?: boolean;\n color?: ContextColorsType;\n size?: 'sm';\n label?: string;\n hint?: string;\n errorMessages?: string | string[];\n successMessages?: string | string[];\n hideDetails?: boolean;\n required?: boolean;\n}\n\ndefineOptions({\n name: 'RuiSwitch',\n inheritAttrs: false,\n});\n\nconst modelValue = defineModel<boolean>({ default: false });\n\nconst {\n disabled = false,\n color = undefined,\n size = undefined,\n label = '',\n hint = '',\n errorMessages = [],\n successMessages = [],\n hideDetails = false,\n required = false,\n} = defineProps<Props>();\n\ndefineSlots<{\n default?: () => any;\n}>();\n\nconst switchStyles = tv({\n slots: {\n // 13px to the label, the gap a checkbox or radio leaves, so the focus ring clears the text\n wrapper: 'relative flex gap-3.25 items-start cursor-pointer group/switch',\n // 40 × 22, nudged down a pixel to sit centred on the label's 24px line\n inner: 'relative w-10 h-5.5 mt-px shrink-0',\n // the off track is the control edge color, 3:1 against the page in both themes\n input: 'peer appearance-none relative w-full h-full rounded-full bg-rui-outline transition-colors duration-150 cursor-pointer focus-visible:focus-ring',\n toggle: [\n 'absolute size-4.5 transition-all duration-75 ease-in-out -translate-y-1/2 top-1/2 rounded-full pointer-events-none',\n 'bg-white left-0.5 shadow-rui-control',\n ].join(' '),\n label: 'text-rui-text text-sm/6',\n },\n variants: {\n checked: {\n true: {\n toggle: 'left-5',\n },\n false: {},\n },\n disabled: {\n true: {\n wrapper: 'cursor-not-allowed',\n input: 'bg-rui-neutral-200! dark:bg-rui-neutral-800! cursor-not-allowed',\n toggle: 'bg-rui-neutral-50! dark:bg-rui-neutral-600! shadow-none!',\n label: 'text-rui-text-disabled',\n },\n },\n size: {\n sm: {\n inner: 'w-8.5 h-4.5 mt-0.75',\n toggle: 'size-3.5',\n },\n },\n // a ring and the message below mark the state; a filled red or green track would read as \"on\"\n validation: {\n error: {\n input: 'ring-1 ring-rui-error',\n },\n success: {\n input: 'ring-1 ring-rui-success',\n },\n },\n color: {\n primary: {},\n secondary: {},\n error: {},\n warning: {},\n info: {},\n success: {},\n },\n },\n compoundVariants: [\n { checked: false, disabled: false, class: { input: 'group-hover/switch:bg-rui-neutral-500 dark:group-hover/switch:bg-rui-neutral-400' } },\n\n // Checked (no color): an inverted neutral track, with a dark knob in dark mode\n { checked: true, disabled: false, class: { input: 'bg-rui-neutral-900 dark:bg-rui-neutral-100', toggle: 'dark:bg-rui-neutral-900' } },\n\n // Checked + color: a solid track with the white knob, in both themes\n { checked: true, disabled: false, color: 'primary', class: { input: 'bg-rui-primary dark:bg-rui-primary', toggle: 'dark:bg-white' } },\n { checked: true, disabled: false, color: 'secondary', class: { input: 'bg-rui-secondary dark:bg-rui-secondary', toggle: 'dark:bg-white' } },\n // a status color's dark `main` is a text tone, so the track takes the deep `darker` under the white knob\n { checked: true, disabled: false, color: 'error', class: { input: 'bg-rui-error dark:bg-rui-error-darker', toggle: 'dark:bg-white' } },\n { checked: true, disabled: false, color: 'warning', class: { input: 'bg-rui-warning dark:bg-rui-warning-darker', toggle: 'dark:bg-white' } },\n { checked: true, disabled: false, color: 'info', class: { input: 'bg-rui-info dark:bg-rui-info-darker', toggle: 'dark:bg-white' } },\n { checked: true, disabled: false, color: 'success', class: { input: 'bg-rui-success dark:bg-rui-success-darker', toggle: 'dark:bg-white' } },\n\n // Size sm + checked: 34 - 14 - 2\n { size: 'sm', checked: true, class: { toggle: 'left-4.5' } },\n ],\n defaultVariants: {\n checked: false,\n disabled: false,\n },\n});\n\nconst { hasError, validation } = useFormTextDetail(\n () => errorMessages,\n () => successMessages,\n);\n\nconst ui = computed<ReturnType<typeof switchStyles>>(() => switchStyles({\n checked: get(modelValue),\n disabled,\n size,\n validation: get(validation),\n color,\n}));\n\nfunction input(event: Event): void {\n const target = event.target;\n if (target instanceof HTMLInputElement)\n set(modelValue, target.checked);\n}\n</script>\n\n<template>\n <div v-bind=\"getRootAttrs($attrs)\">\n <label\n :class=\"ui.wrapper()\"\n :data-disabled=\"disabled || undefined\"\n :data-checked=\"modelValue || undefined\"\n :data-error=\"hasError ? '' : undefined\"\n >\n <div :class=\"ui.inner()\">\n <input\n :checked=\"modelValue\"\n type=\"checkbox\"\n :class=\"ui.input()\"\n :disabled=\"disabled\"\n :aria-invalid=\"hasError\"\n v-bind=\"getNonRootAttrs($attrs)\"\n @input=\"input($event)\"\n />\n <div :class=\"ui.toggle()\" />\n </div>\n <span\n v-if=\"label || $slots.default\"\n :class=\"ui.label()\"\n >\n <slot>{{ label }}</slot>\n <span\n v-if=\"required\"\n class=\"text-rui-error\"\n >\n *\n </span>\n </span>\n </label>\n <RuiFormTextDetail\n v-if=\"!hideDetails\"\n class=\"pt-1\"\n :error-messages=\"errorMessages\"\n :success-messages=\"successMessages\"\n :hint=\"hint\"\n />\n </div>\n</template>\n"],"mappings":"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"}
1
+ {"version":3,"file":"RuiSwitch.vue_vue_type_script_setup_true_lang.js","names":["$attrs","$slots","_useModel","_openBlock","_createElementBlock","_normalizeProps","_guardReactiveProps","_unref","_createElementVNode","_normalizeClass","_mergeProps","_renderSlot","_createTextVNode","_toDisplayString","_createCommentVNode","_createBlock","RuiFormTextDetail"],"sources":["../../../../src/components/forms/switch/RuiSwitch.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport type { ContextColorsType } from '@/consts/colors';\nimport RuiFormTextDetail from '@/components/helpers/RuiFormTextDetail.vue';\nimport { type FormDetails, useFormDetails, useFormTextDetail } from '@/utils/form-text-detail';\nimport { getNonRootAttrs, getRootAttrs } from '@/utils/helpers';\nimport { tv } from '@/utils/tv';\n\nexport interface Props {\n disabled?: boolean;\n color?: ContextColorsType;\n size?: 'sm';\n label?: string;\n hint?: string;\n errorMessages?: string | string[];\n successMessages?: string | string[];\n /** The line under the control for its hint and messages: `reserve`, `auto` or `hidden`; falls back to the nearest `RuiFieldDefaults`, then the app default, then `reserve`. */\n details?: FormDetails;\n /** @deprecated Use `details=\"hidden\"`. Removed in 4.0. */\n hideDetails?: boolean;\n /** Puts the hint or message under the label text instead of under the track, so a list of switches keeps one text column. */\n detailsUnderLabel?: boolean;\n required?: boolean;\n}\n\ndefineOptions({\n name: 'RuiSwitch',\n inheritAttrs: false,\n});\n\nconst modelValue = defineModel<boolean>({ default: false });\n\nconst {\n disabled = false,\n color = undefined,\n size = undefined,\n label = '',\n hint = '',\n errorMessages = [],\n successMessages = [],\n details = undefined,\n hideDetails = false,\n detailsUnderLabel = false,\n required = false,\n} = defineProps<Props>();\n\ndefineSlots<{\n default?: () => any;\n}>();\n\nconst switchStyles = tv({\n slots: {\n // 13px to the label, the gap a checkbox or radio leaves, so the focus ring clears the text\n wrapper: 'relative flex gap-3.25 items-start cursor-pointer group/switch',\n // 40 × 22, nudged down a pixel to sit centred on the label's 24px line\n inner: 'relative w-10 h-5.5 mt-px shrink-0',\n // the off track is the control edge color, 3:1 against the page in both themes\n input: 'peer appearance-none relative w-full h-full rounded-full bg-rui-outline transition-colors duration-150 cursor-pointer focus-visible:focus-ring',\n toggle: [\n 'absolute size-4.5 transition-all duration-75 ease-in-out -translate-y-1/2 top-1/2 rounded-full pointer-events-none',\n 'bg-white left-0.5 shadow-rui-control',\n ].join(' '),\n label: 'text-rui-text text-sm/6',\n details: '',\n },\n variants: {\n // indented by the track and the 13px gap, so the message starts where the label does\n underLabel: {\n true: { details: 'pl-13.25' },\n false: {},\n },\n checked: {\n true: {\n toggle: 'left-5',\n },\n false: {},\n },\n disabled: {\n true: {\n wrapper: 'cursor-not-allowed',\n input: 'bg-rui-neutral-200! dark:bg-rui-neutral-800! cursor-not-allowed',\n toggle: 'bg-rui-neutral-50! dark:bg-rui-neutral-600! shadow-none!',\n label: 'text-rui-text-disabled',\n },\n },\n size: {\n sm: {\n inner: 'w-8.5 h-4.5 mt-0.75',\n toggle: 'size-3.5',\n },\n },\n // a ring and the message below mark the state; a filled red or green track would read as \"on\"\n validation: {\n error: {\n input: 'ring-1 ring-rui-error',\n },\n success: {\n input: 'ring-1 ring-rui-success',\n },\n },\n color: {\n primary: {},\n secondary: {},\n error: {},\n warning: {},\n info: {},\n success: {},\n },\n },\n compoundVariants: [\n { checked: false, disabled: false, class: { input: 'group-hover/switch:bg-rui-neutral-500 dark:group-hover/switch:bg-rui-neutral-400' } },\n\n // Checked (no color): an inverted neutral track, with a dark knob in dark mode\n { checked: true, disabled: false, class: { input: 'bg-rui-neutral-900 dark:bg-rui-neutral-100', toggle: 'dark:bg-rui-neutral-900' } },\n\n // Checked + color: a solid track with the white knob, in both themes\n { checked: true, disabled: false, color: 'primary', class: { input: 'bg-rui-primary dark:bg-rui-primary', toggle: 'dark:bg-white' } },\n { checked: true, disabled: false, color: 'secondary', class: { input: 'bg-rui-secondary dark:bg-rui-secondary', toggle: 'dark:bg-white' } },\n // a status color's dark `main` is a text tone, so the track takes the deep `darker` under the white knob\n { checked: true, disabled: false, color: 'error', class: { input: 'bg-rui-error dark:bg-rui-error-darker', toggle: 'dark:bg-white' } },\n { checked: true, disabled: false, color: 'warning', class: { input: 'bg-rui-warning dark:bg-rui-warning-darker', toggle: 'dark:bg-white' } },\n { checked: true, disabled: false, color: 'info', class: { input: 'bg-rui-info dark:bg-rui-info-darker', toggle: 'dark:bg-white' } },\n { checked: true, disabled: false, color: 'success', class: { input: 'bg-rui-success dark:bg-rui-success-darker', toggle: 'dark:bg-white' } },\n\n // Size sm + checked: 34 - 14 - 2\n { size: 'sm', checked: true, class: { toggle: 'left-4.5' } },\n // sm: a 34px track\n { size: 'sm', underLabel: true, class: { details: 'pl-11.75' } },\n ],\n defaultVariants: {\n checked: false,\n disabled: false,\n },\n});\n\nconst { hasError, validation } = useFormTextDetail(\n () => errorMessages,\n () => successMessages,\n);\nconst detailsMode = useFormDetails(() => details, () => hideDetails);\n\nconst ui = computed<ReturnType<typeof switchStyles>>(() => switchStyles({\n checked: get(modelValue),\n disabled,\n size,\n validation: get(validation),\n color,\n underLabel: detailsUnderLabel,\n}));\n\nfunction input(event: Event): void {\n const target = event.target;\n if (target instanceof HTMLInputElement)\n set(modelValue, target.checked);\n}\n</script>\n\n<template>\n <div v-bind=\"getRootAttrs($attrs)\">\n <label\n :class=\"ui.wrapper()\"\n :data-disabled=\"disabled || undefined\"\n :data-checked=\"modelValue || undefined\"\n :data-error=\"hasError ? '' : undefined\"\n >\n <div :class=\"ui.inner()\">\n <input\n :checked=\"modelValue\"\n type=\"checkbox\"\n :class=\"ui.input()\"\n :disabled=\"disabled\"\n :aria-invalid=\"hasError\"\n v-bind=\"getNonRootAttrs($attrs)\"\n @input=\"input($event)\"\n />\n <div :class=\"ui.toggle()\" />\n </div>\n <span\n v-if=\"label || $slots.default\"\n :class=\"ui.label()\"\n >\n <slot>{{ label }}</slot>\n <span\n v-if=\"required\"\n class=\"text-rui-error\"\n >\n *\n </span>\n </span>\n </label>\n <RuiFormTextDetail\n v-if=\"detailsMode !== 'hidden'\"\n :class=\"ui.details()\"\n :details=\"detailsMode\"\n :error-messages=\"errorMessages\"\n :success-messages=\"successMessages\"\n :hint=\"hint\"\n />\n </div>\n</template>\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"RuiTextArea.js","names":["_sfc_main"],"sources":["../../../../src/components/forms/text-area/RuiTextArea.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport type { ContextColorsType } from '@/consts/colors';\nimport type { RuiIcons } from '@/icons';\nimport RuiButton from '@/components/buttons/button/RuiButton.vue';\nimport RuiFieldLabel from '@/components/forms/field-label/RuiFieldLabel.vue';\nimport { textAreaStyles } from '@/components/forms/text-area/text-area-styles';\nimport RuiFormTextDetail from '@/components/helpers/RuiFormTextDetail.vue';\nimport RuiIcon from '@/components/icons/RuiIcon.vue';\nimport { type LabelPlacement, useLabelPlacement } from '@/composables/defaults/field';\nimport { usePrependAppendWidth } from '@/composables/forms/use-prepend-append-width';\nimport { useTimeoutManager } from '@/composables/timeout-manager';\nimport { useFormTextDetail } from '@/utils/form-text-detail';\nimport { getNonRootAttrs, getRootAttrs } from '@/utils/helpers';\n\nexport interface TextAreaProps {\n label?: string;\n placeholder?: string;\n disabled?: boolean;\n /** Where the label shows; falls back to the nearest `RuiFieldDefaults`, then the app default, then `top`. */\n labelPlacement?: LabelPlacement;\n color?: ContextColorsType;\n textColor?: ContextColorsType;\n dense?: boolean;\n hint?: string;\n errorMessages?: string | string[];\n successMessages?: string | string[];\n hideDetails?: boolean;\n prependIcon?: RuiIcons;\n appendIcon?: RuiIcons;\n readonly?: boolean;\n clearable?: boolean;\n noResize?: boolean;\n minRows?: number | string;\n maxRows?: number | string;\n rowHeight?: number | string;\n autoGrow?: boolean;\n required?: boolean;\n}\n\ndefineOptions({\n name: 'RuiTextArea',\n inheritAttrs: false,\n});\n\nconst modelValue = defineModel<string>({ required: true });\n\nconst {\n label = '',\n placeholder = '',\n disabled = false,\n labelPlacement = undefined,\n color = undefined,\n textColor = undefined,\n dense = false,\n hint = '',\n errorMessages = [],\n successMessages = [],\n hideDetails = false,\n prependIcon = undefined,\n appendIcon = undefined,\n readonly = false,\n clearable = false,\n noResize = false,\n minRows = 2,\n rowHeight = 1.5,\n maxRows = undefined,\n autoGrow = false,\n required = false,\n} = defineProps<TextAreaProps>();\n\nconst emit = defineEmits<{\n 'click:clear': [];\n}>();\n\ndefineSlots<{\n prepend?: () => any;\n append?: () => any;\n}>();\n\nconst isHovered = ref<boolean>(false);\nconst showClearButton = ref<boolean>(false);\n\nconst prepend = useTemplateRef<HTMLDivElement>('prepend');\nconst append = useTemplateRef<HTMLDivElement>('append');\nconst textarea = useTemplateRef<HTMLTextAreaElement>('textarea');\nconst textareaSizer = useTemplateRef<HTMLTextAreaElement>('textareaSizer');\n\nconst generatedId = useId();\nconst attrs = useAttrs();\n\nconst { focused } = useFocus(textarea);\nconst placement = useLabelPlacement(() => labelPlacement);\nconst { clear: cancelClearHide, create: delayClearHide } = useTimeoutManager();\nconst { prependWidth, appendWidth } = usePrependAppendWidth(prepend, append, 24);\nconst { hasError, hasSuccess, hasMessages, validation } = useFormTextDetail(\n () => errorMessages,\n () => successMessages,\n);\n\nconst textareaId = computed<string>(() => {\n const id = attrs.id;\n return typeof id === 'string' && id ? id : generatedId;\n});\n\nconst showClearIcon = computed<boolean>(() => clearable && !!get(modelValue) && !disabled && !readonly);\n\nconst effectiveTextColor = computed<ContextColorsType | undefined>(() => {\n if (get(hasError))\n return 'error';\n if (get(hasSuccess))\n return 'success';\n if (textColor && !get(hasMessages))\n return textColor;\n return undefined;\n});\n\nconst effectiveColor = computed<ContextColorsType | undefined>(() => get(validation) ?? color);\n\nconst ui = computed<ReturnType<typeof textAreaStyles>>(() => textAreaStyles({\n dense,\n disabled,\n readonly,\n noResize,\n hovered: get(isHovered),\n focused: get(focused),\n color: get(effectiveColor),\n textColor: get(effectiveTextColor),\n validation: get(validation),\n}));\n\nconst wrapperStyle = computed<Record<string, string>>(() => ({\n '--prepend-w': get(prependWidth),\n '--append-w': get(appendWidth),\n}));\n\nconst fieldStyles = computed<{ minHeight: string; maxHeight?: string }>(() => {\n const height = Number(rowHeight);\n const min = Number(minRows);\n const max = Number(maxRows);\n const value: { minHeight: string; maxHeight?: string } = {\n minHeight: `${min * height + 0.75}rem`,\n };\n if (max)\n value.maxHeight = `${max * height + 0.75}rem`;\n\n return value;\n});\n\nfunction clearIconClicked(): void {\n set(modelValue, '');\n emit('click:clear');\n}\n\nfunction computeFieldHeight(newVal?: string, oldVal?: string): void {\n if (!autoGrow)\n return;\n\n const field = get(textarea);\n const fieldValue = newVal ?? get(modelValue);\n const fieldSizer = get(textareaSizer);\n if (!(field && fieldSizer))\n return;\n\n nextTick(() => {\n const sizerHeight = fieldSizer.scrollHeight;\n const fieldHeight = field.scrollHeight;\n let height = `${Math.max(sizerHeight, fieldHeight) / 16}rem`;\n if (oldVal && oldVal.length > fieldValue.length)\n height = `${Math.min(sizerHeight, fieldHeight) / 16}rem`;\n\n field.style.height = height;\n });\n}\n\nwatch(focused, (value) => {\n if (value) {\n // a refocus within the delay keeps the button\n cancelClearHide();\n set(showClearButton, true);\n }\n else {\n delayClearHide(() => set(showClearButton, false), 500);\n }\n});\n\nwatchDebounced(modelValue, computeFieldHeight, { debounce: 50 });\n\nonMounted(computeFieldHeight);\n\ndefineExpose({\n focus: () => get(textarea)?.focus(),\n element: textarea,\n});\n</script>\n\n<template>\n <div v-bind=\"getRootAttrs($attrs)\">\n <RuiFieldLabel\n v-if=\"label\"\n :text=\"label\"\n :for=\"textareaId\"\n :hidden=\"placement === 'hidden'\"\n :required=\"required\"\n :disabled=\"disabled\"\n />\n <div\n :class=\"ui.wrapper()\"\n :style=\"wrapperStyle\"\n data-id=\"wrapper\"\n @mouseenter=\"isHovered = true\"\n @mouseleave=\"isHovered = false\"\n >\n <div\n v-if=\"$slots.prepend || prependIcon\"\n ref=\"prepend\"\n :class=\"ui.prepend()\"\n data-id=\"prepend\"\n >\n <slot\n v-if=\"$slots.prepend\"\n name=\"prepend\"\n />\n <div\n v-else-if=\"prependIcon\"\n :class=\"ui.icon()\"\n >\n <RuiIcon\n :name=\"prependIcon\"\n :size=\"18\"\n />\n </div>\n </div>\n <div :class=\"ui.inputWrapper()\">\n <textarea\n v-if=\"autoGrow\"\n ref=\"textareaSizer\"\n :value=\"modelValue\"\n :class=\"ui.textareaSizer()\"\n :style=\"fieldStyles\"\n aria-hidden=\"true\"\n disabled\n readonly\n />\n <textarea\n :id=\"textareaId\"\n ref=\"textarea\"\n v-model=\"modelValue\"\n :placeholder=\"placeholder || ' '\"\n :class=\"ui.textarea()\"\n :style=\"fieldStyles\"\n :disabled=\"disabled\"\n :readonly=\"readonly\"\n :aria-invalid=\"hasError\"\n v-bind=\"getNonRootAttrs($attrs)\"\n />\n <fieldset :class=\"ui.fieldset()\" />\n </div>\n <div\n v-if=\"$slots.append || appendIcon || showClearIcon\"\n ref=\"append\"\n :class=\"ui.append()\"\n data-id=\"append\"\n >\n <RuiButton\n v-if=\"showClearIcon\"\n :class=\"[ui.clearButton(), { hidden: !showClearButton }]\"\n variant=\"text\"\n type=\"button\"\n icon\n data-id=\"clear-btn\"\n aria-label=\"Clear\"\n tabindex=\"-1\"\n @click.stop=\"clearIconClicked()\"\n >\n <RuiIcon\n name=\"lu-x\"\n size=\"16\"\n />\n </RuiButton>\n <slot\n v-if=\"$slots.append\"\n name=\"append\"\n />\n <div\n v-else-if=\"appendIcon\"\n :class=\"ui.icon()\"\n >\n <RuiIcon\n :name=\"appendIcon\"\n :size=\"18\"\n />\n </div>\n </div>\n </div>\n <RuiFormTextDetail\n v-if=\"!hideDetails\"\n :class=\"ui.details()\"\n :error-messages=\"errorMessages\"\n :success-messages=\"successMessages\"\n :hint=\"hint\"\n />\n </div>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"RuiTextArea.js","names":["_sfc_main"],"sources":["../../../../src/components/forms/text-area/RuiTextArea.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport type { ContextColorsType } from '@/consts/colors';\nimport type { RuiIcons } from '@/icons';\nimport RuiButton from '@/components/buttons/button/RuiButton.vue';\nimport RuiFieldLabel from '@/components/forms/field-label/RuiFieldLabel.vue';\nimport { textAreaStyles } from '@/components/forms/text-area/text-area-styles';\nimport RuiFormTextDetail from '@/components/helpers/RuiFormTextDetail.vue';\nimport RuiIcon from '@/components/icons/RuiIcon.vue';\nimport { type LabelPlacement, useLabelPlacement } from '@/composables/defaults/field';\nimport { usePrependAppendWidth } from '@/composables/forms/use-prepend-append-width';\nimport { useTimeoutManager } from '@/composables/timeout-manager';\nimport { type FormDetails, useFormDetails, useFormTextDetail } from '@/utils/form-text-detail';\nimport { getNonRootAttrs, getRootAttrs } from '@/utils/helpers';\n\nexport interface TextAreaProps {\n label?: string;\n placeholder?: string;\n disabled?: boolean;\n /** Where the label shows; falls back to the nearest `RuiFieldDefaults`, then the app default, then `top`. */\n labelPlacement?: LabelPlacement;\n color?: ContextColorsType;\n textColor?: ContextColorsType;\n dense?: boolean;\n hint?: string;\n errorMessages?: string | string[];\n successMessages?: string | string[];\n /** The line under the field for its hint and messages: `reserve`, `auto` or `hidden`; falls back to the nearest `RuiFieldDefaults`, then the app default, then `reserve`. */\n details?: FormDetails;\n /** @deprecated Use `details=\"hidden\"`. Removed in 4.0. */\n hideDetails?: boolean;\n prependIcon?: RuiIcons;\n appendIcon?: RuiIcons;\n readonly?: boolean;\n clearable?: boolean;\n noResize?: boolean;\n minRows?: number | string;\n maxRows?: number | string;\n rowHeight?: number | string;\n autoGrow?: boolean;\n required?: boolean;\n}\n\ndefineOptions({\n name: 'RuiTextArea',\n inheritAttrs: false,\n});\n\nconst modelValue = defineModel<string>({ required: true });\n\nconst {\n label = '',\n placeholder = '',\n disabled = false,\n labelPlacement = undefined,\n color = undefined,\n textColor = undefined,\n dense = false,\n hint = '',\n errorMessages = [],\n successMessages = [],\n details = undefined,\n hideDetails = false,\n prependIcon = undefined,\n appendIcon = undefined,\n readonly = false,\n clearable = false,\n noResize = false,\n minRows = 2,\n rowHeight = 1.5,\n maxRows = undefined,\n autoGrow = false,\n required = false,\n} = defineProps<TextAreaProps>();\n\nconst emit = defineEmits<{\n 'click:clear': [];\n}>();\n\ndefineSlots<{\n prepend?: () => any;\n append?: () => any;\n}>();\n\nconst isHovered = ref<boolean>(false);\nconst showClearButton = ref<boolean>(false);\n\nconst prepend = useTemplateRef<HTMLDivElement>('prepend');\nconst append = useTemplateRef<HTMLDivElement>('append');\nconst textarea = useTemplateRef<HTMLTextAreaElement>('textarea');\nconst textareaSizer = useTemplateRef<HTMLTextAreaElement>('textareaSizer');\n\nconst generatedId = useId();\nconst attrs = useAttrs();\n\nconst { focused } = useFocus(textarea);\nconst placement = useLabelPlacement(() => labelPlacement);\nconst { clear: cancelClearHide, create: delayClearHide } = useTimeoutManager();\nconst { prependWidth, appendWidth } = usePrependAppendWidth(prepend, append, 24);\nconst { hasError, hasSuccess, hasMessages, validation } = useFormTextDetail(\n () => errorMessages,\n () => successMessages,\n);\nconst detailsMode = useFormDetails(() => details, () => hideDetails);\n\nconst textareaId = computed<string>(() => {\n const id = attrs.id;\n return typeof id === 'string' && id ? id : generatedId;\n});\n\nconst showClearIcon = computed<boolean>(() => clearable && !!get(modelValue) && !disabled && !readonly);\n\nconst effectiveTextColor = computed<ContextColorsType | undefined>(() => {\n if (get(hasError))\n return 'error';\n if (get(hasSuccess))\n return 'success';\n if (textColor && !get(hasMessages))\n return textColor;\n return undefined;\n});\n\nconst effectiveColor = computed<ContextColorsType | undefined>(() => get(validation) ?? color);\n\nconst ui = computed<ReturnType<typeof textAreaStyles>>(() => textAreaStyles({\n dense,\n disabled,\n readonly,\n noResize,\n hovered: get(isHovered),\n focused: get(focused),\n color: get(effectiveColor),\n textColor: get(effectiveTextColor),\n validation: get(validation),\n}));\n\nconst wrapperStyle = computed<Record<string, string>>(() => ({\n '--prepend-w': get(prependWidth),\n '--append-w': get(appendWidth),\n}));\n\nconst fieldStyles = computed<{ minHeight: string; maxHeight?: string }>(() => {\n const height = Number(rowHeight);\n const min = Number(minRows);\n const max = Number(maxRows);\n const value: { minHeight: string; maxHeight?: string } = {\n minHeight: `${min * height + 0.75}rem`,\n };\n if (max)\n value.maxHeight = `${max * height + 0.75}rem`;\n\n return value;\n});\n\nfunction clearIconClicked(): void {\n set(modelValue, '');\n emit('click:clear');\n}\n\nfunction computeFieldHeight(newVal?: string, oldVal?: string): void {\n if (!autoGrow)\n return;\n\n const field = get(textarea);\n const fieldValue = newVal ?? get(modelValue);\n const fieldSizer = get(textareaSizer);\n if (!(field && fieldSizer))\n return;\n\n nextTick(() => {\n const sizerHeight = fieldSizer.scrollHeight;\n const fieldHeight = field.scrollHeight;\n let height = `${Math.max(sizerHeight, fieldHeight) / 16}rem`;\n if (oldVal && oldVal.length > fieldValue.length)\n height = `${Math.min(sizerHeight, fieldHeight) / 16}rem`;\n\n field.style.height = height;\n });\n}\n\nwatch(focused, (value) => {\n if (value) {\n // a refocus within the delay keeps the button\n cancelClearHide();\n set(showClearButton, true);\n }\n else {\n delayClearHide(() => set(showClearButton, false), 500);\n }\n});\n\nwatchDebounced(modelValue, computeFieldHeight, { debounce: 50 });\n\nonMounted(computeFieldHeight);\n\ndefineExpose({\n focus: () => get(textarea)?.focus(),\n element: textarea,\n});\n</script>\n\n<template>\n <div v-bind=\"getRootAttrs($attrs)\">\n <RuiFieldLabel\n v-if=\"label\"\n :text=\"label\"\n :for=\"textareaId\"\n :hidden=\"placement === 'hidden'\"\n :required=\"required\"\n :disabled=\"disabled\"\n />\n <div\n :class=\"ui.wrapper()\"\n :style=\"wrapperStyle\"\n data-id=\"wrapper\"\n @mouseenter=\"isHovered = true\"\n @mouseleave=\"isHovered = false\"\n >\n <div\n v-if=\"$slots.prepend || prependIcon\"\n ref=\"prepend\"\n :class=\"ui.prepend()\"\n data-id=\"prepend\"\n >\n <slot\n v-if=\"$slots.prepend\"\n name=\"prepend\"\n />\n <div\n v-else-if=\"prependIcon\"\n :class=\"ui.icon()\"\n >\n <RuiIcon\n :name=\"prependIcon\"\n :size=\"18\"\n />\n </div>\n </div>\n <div :class=\"ui.inputWrapper()\">\n <textarea\n v-if=\"autoGrow\"\n ref=\"textareaSizer\"\n :value=\"modelValue\"\n :class=\"ui.textareaSizer()\"\n :style=\"fieldStyles\"\n aria-hidden=\"true\"\n disabled\n readonly\n />\n <textarea\n :id=\"textareaId\"\n ref=\"textarea\"\n v-model=\"modelValue\"\n :placeholder=\"placeholder || ' '\"\n :class=\"ui.textarea()\"\n :style=\"fieldStyles\"\n :disabled=\"disabled\"\n :readonly=\"readonly\"\n :aria-invalid=\"hasError\"\n v-bind=\"getNonRootAttrs($attrs)\"\n />\n <fieldset :class=\"ui.fieldset()\" />\n </div>\n <div\n v-if=\"$slots.append || appendIcon || showClearIcon\"\n ref=\"append\"\n :class=\"ui.append()\"\n data-id=\"append\"\n >\n <RuiButton\n v-if=\"showClearIcon\"\n :class=\"[ui.clearButton(), { hidden: !showClearButton }]\"\n variant=\"text\"\n type=\"button\"\n icon\n data-id=\"clear-btn\"\n aria-label=\"Clear\"\n tabindex=\"-1\"\n @click.stop=\"clearIconClicked()\"\n >\n <RuiIcon\n name=\"lu-x\"\n size=\"16\"\n />\n </RuiButton>\n <slot\n v-if=\"$slots.append\"\n name=\"append\"\n />\n <div\n v-else-if=\"appendIcon\"\n :class=\"ui.icon()\"\n >\n <RuiIcon\n :name=\"appendIcon\"\n :size=\"18\"\n />\n </div>\n </div>\n </div>\n <RuiFormTextDetail\n v-if=\"detailsMode !== 'hidden'\"\n :details=\"detailsMode\"\n :error-messages=\"errorMessages\"\n :success-messages=\"successMessages\"\n :hint=\"hint\"\n />\n </div>\n</template>\n"],"mappings":""}
@@ -1,6 +1,7 @@
1
1
  import type { ContextColorsType } from '../../../consts/colors.js';
2
2
  import type { RuiIcons } from '../../../icons/index.js';
3
3
  import { type LabelPlacement } from '../../../composables/defaults/field.js';
4
+ import { type FormDetails } from '../../../utils/form-text-detail.js';
4
5
  export interface TextAreaProps {
5
6
  label?: string;
6
7
  placeholder?: string;
@@ -13,6 +14,9 @@ export interface TextAreaProps {
13
14
  hint?: string;
14
15
  errorMessages?: string | string[];
15
16
  successMessages?: string | string[];
17
+ /** The line under the field for its hint and messages: `reserve`, `auto` or `hidden`; falls back to the nearest `RuiFieldDefaults`, then the app default, then `reserve`. */
18
+ details?: FormDetails;
19
+ /** @deprecated Use `details="hidden"`. Removed in 4.0. */
16
20
  hideDetails?: boolean;
17
21
  prependIcon?: RuiIcons;
18
22
  appendIcon?: RuiIcons;
@@ -3,7 +3,7 @@ import { get, set, watchDebounced } from "../../../vendor/@vueuse/shared/dist/in
3
3
  import { useFocus } from "../../../vendor/@vueuse/core/dist/index.js";
4
4
  import RuiIcon_default from "../../icons/RuiIcon.js";
5
5
  import RuiButton_default from "../../buttons/button/RuiButton.js";
6
- import { useFormTextDetail } from "../../../utils/form-text-detail.js";
6
+ import { useFormDetails, useFormTextDetail } from "../../../utils/form-text-detail.js";
7
7
  import RuiFormTextDetail_default from "../../helpers/RuiFormTextDetail.js";
8
8
  import { useTimeoutManager } from "../../../composables/timeout-manager.js";
9
9
  import RuiFieldLabel_default from "../field-label/RuiFieldLabel.js";
@@ -41,6 +41,7 @@ var RuiTextArea_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defi
41
41
  hint: { default: "" },
42
42
  errorMessages: { default: () => [] },
43
43
  successMessages: { default: () => [] },
44
+ details: { default: () => void 0 },
44
45
  hideDetails: {
45
46
  type: Boolean,
46
47
  default: false
@@ -91,6 +92,7 @@ var RuiTextArea_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defi
91
92
  const { clear: cancelClearHide, create: delayClearHide } = useTimeoutManager();
92
93
  const { prependWidth, appendWidth } = usePrependAppendWidth(prepend, append, 24);
93
94
  const { hasError, hasSuccess, hasMessages, validation } = useFormTextDetail(() => __props.errorMessages, () => __props.successMessages);
95
+ const detailsMode = useFormDetails(() => __props.details, () => __props.hideDetails);
94
96
  const textareaId = computed(() => {
95
97
  const id = attrs.id;
96
98
  return typeof id === "string" && id ? id : generatedId;
@@ -247,14 +249,14 @@ var RuiTextArea_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defi
247
249
  size: 18
248
250
  }, null, 8, ["name"])], 2)) : createCommentVNode("", true)], 2)) : createCommentVNode("", true)
249
251
  ], 38),
250
- !__props.hideDetails ? (openBlock(), createBlock(RuiFormTextDetail_default, {
252
+ unref(detailsMode) !== "hidden" ? (openBlock(), createBlock(RuiFormTextDetail_default, {
251
253
  key: 1,
252
- class: normalizeClass(unref(ui).details()),
254
+ details: unref(detailsMode),
253
255
  "error-messages": __props.errorMessages,
254
256
  "success-messages": __props.successMessages,
255
257
  hint: __props.hint
256
258
  }, null, 8, [
257
- "class",
259
+ "details",
258
260
  "error-messages",
259
261
  "success-messages",
260
262
  "hint"
@@ -1 +1 @@
1
- {"version":3,"file":"RuiTextArea.vue_vue_type_script_setup_true_lang.js","names":["$attrs","$slots","_useModel","_openBlock","_createElementBlock","_normalizeProps","_guardReactiveProps","_unref","_createBlock","RuiFieldLabel","_createCommentVNode","_createElementVNode","_normalizeClass","_normalizeStyle","_renderSlot","_createVNode","RuiIcon","_withDirectives","_mergeProps","_vModelText","RuiButton","_withModifiers","_withCtx","RuiFormTextDetail"],"sources":["../../../../src/components/forms/text-area/RuiTextArea.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport type { ContextColorsType } from '@/consts/colors';\nimport type { RuiIcons } from '@/icons';\nimport RuiButton from '@/components/buttons/button/RuiButton.vue';\nimport RuiFieldLabel from '@/components/forms/field-label/RuiFieldLabel.vue';\nimport { textAreaStyles } from '@/components/forms/text-area/text-area-styles';\nimport RuiFormTextDetail from '@/components/helpers/RuiFormTextDetail.vue';\nimport RuiIcon from '@/components/icons/RuiIcon.vue';\nimport { type LabelPlacement, useLabelPlacement } from '@/composables/defaults/field';\nimport { usePrependAppendWidth } from '@/composables/forms/use-prepend-append-width';\nimport { useTimeoutManager } from '@/composables/timeout-manager';\nimport { useFormTextDetail } from '@/utils/form-text-detail';\nimport { getNonRootAttrs, getRootAttrs } from '@/utils/helpers';\n\nexport interface TextAreaProps {\n label?: string;\n placeholder?: string;\n disabled?: boolean;\n /** Where the label shows; falls back to the nearest `RuiFieldDefaults`, then the app default, then `top`. */\n labelPlacement?: LabelPlacement;\n color?: ContextColorsType;\n textColor?: ContextColorsType;\n dense?: boolean;\n hint?: string;\n errorMessages?: string | string[];\n successMessages?: string | string[];\n hideDetails?: boolean;\n prependIcon?: RuiIcons;\n appendIcon?: RuiIcons;\n readonly?: boolean;\n clearable?: boolean;\n noResize?: boolean;\n minRows?: number | string;\n maxRows?: number | string;\n rowHeight?: number | string;\n autoGrow?: boolean;\n required?: boolean;\n}\n\ndefineOptions({\n name: 'RuiTextArea',\n inheritAttrs: false,\n});\n\nconst modelValue = defineModel<string>({ required: true });\n\nconst {\n label = '',\n placeholder = '',\n disabled = false,\n labelPlacement = undefined,\n color = undefined,\n textColor = undefined,\n dense = false,\n hint = '',\n errorMessages = [],\n successMessages = [],\n hideDetails = false,\n prependIcon = undefined,\n appendIcon = undefined,\n readonly = false,\n clearable = false,\n noResize = false,\n minRows = 2,\n rowHeight = 1.5,\n maxRows = undefined,\n autoGrow = false,\n required = false,\n} = defineProps<TextAreaProps>();\n\nconst emit = defineEmits<{\n 'click:clear': [];\n}>();\n\ndefineSlots<{\n prepend?: () => any;\n append?: () => any;\n}>();\n\nconst isHovered = ref<boolean>(false);\nconst showClearButton = ref<boolean>(false);\n\nconst prepend = useTemplateRef<HTMLDivElement>('prepend');\nconst append = useTemplateRef<HTMLDivElement>('append');\nconst textarea = useTemplateRef<HTMLTextAreaElement>('textarea');\nconst textareaSizer = useTemplateRef<HTMLTextAreaElement>('textareaSizer');\n\nconst generatedId = useId();\nconst attrs = useAttrs();\n\nconst { focused } = useFocus(textarea);\nconst placement = useLabelPlacement(() => labelPlacement);\nconst { clear: cancelClearHide, create: delayClearHide } = useTimeoutManager();\nconst { prependWidth, appendWidth } = usePrependAppendWidth(prepend, append, 24);\nconst { hasError, hasSuccess, hasMessages, validation } = useFormTextDetail(\n () => errorMessages,\n () => successMessages,\n);\n\nconst textareaId = computed<string>(() => {\n const id = attrs.id;\n return typeof id === 'string' && id ? id : generatedId;\n});\n\nconst showClearIcon = computed<boolean>(() => clearable && !!get(modelValue) && !disabled && !readonly);\n\nconst effectiveTextColor = computed<ContextColorsType | undefined>(() => {\n if (get(hasError))\n return 'error';\n if (get(hasSuccess))\n return 'success';\n if (textColor && !get(hasMessages))\n return textColor;\n return undefined;\n});\n\nconst effectiveColor = computed<ContextColorsType | undefined>(() => get(validation) ?? color);\n\nconst ui = computed<ReturnType<typeof textAreaStyles>>(() => textAreaStyles({\n dense,\n disabled,\n readonly,\n noResize,\n hovered: get(isHovered),\n focused: get(focused),\n color: get(effectiveColor),\n textColor: get(effectiveTextColor),\n validation: get(validation),\n}));\n\nconst wrapperStyle = computed<Record<string, string>>(() => ({\n '--prepend-w': get(prependWidth),\n '--append-w': get(appendWidth),\n}));\n\nconst fieldStyles = computed<{ minHeight: string; maxHeight?: string }>(() => {\n const height = Number(rowHeight);\n const min = Number(minRows);\n const max = Number(maxRows);\n const value: { minHeight: string; maxHeight?: string } = {\n minHeight: `${min * height + 0.75}rem`,\n };\n if (max)\n value.maxHeight = `${max * height + 0.75}rem`;\n\n return value;\n});\n\nfunction clearIconClicked(): void {\n set(modelValue, '');\n emit('click:clear');\n}\n\nfunction computeFieldHeight(newVal?: string, oldVal?: string): void {\n if (!autoGrow)\n return;\n\n const field = get(textarea);\n const fieldValue = newVal ?? get(modelValue);\n const fieldSizer = get(textareaSizer);\n if (!(field && fieldSizer))\n return;\n\n nextTick(() => {\n const sizerHeight = fieldSizer.scrollHeight;\n const fieldHeight = field.scrollHeight;\n let height = `${Math.max(sizerHeight, fieldHeight) / 16}rem`;\n if (oldVal && oldVal.length > fieldValue.length)\n height = `${Math.min(sizerHeight, fieldHeight) / 16}rem`;\n\n field.style.height = height;\n });\n}\n\nwatch(focused, (value) => {\n if (value) {\n // a refocus within the delay keeps the button\n cancelClearHide();\n set(showClearButton, true);\n }\n else {\n delayClearHide(() => set(showClearButton, false), 500);\n }\n});\n\nwatchDebounced(modelValue, computeFieldHeight, { debounce: 50 });\n\nonMounted(computeFieldHeight);\n\ndefineExpose({\n focus: () => get(textarea)?.focus(),\n element: textarea,\n});\n</script>\n\n<template>\n <div v-bind=\"getRootAttrs($attrs)\">\n <RuiFieldLabel\n v-if=\"label\"\n :text=\"label\"\n :for=\"textareaId\"\n :hidden=\"placement === 'hidden'\"\n :required=\"required\"\n :disabled=\"disabled\"\n />\n <div\n :class=\"ui.wrapper()\"\n :style=\"wrapperStyle\"\n data-id=\"wrapper\"\n @mouseenter=\"isHovered = true\"\n @mouseleave=\"isHovered = false\"\n >\n <div\n v-if=\"$slots.prepend || prependIcon\"\n ref=\"prepend\"\n :class=\"ui.prepend()\"\n data-id=\"prepend\"\n >\n <slot\n v-if=\"$slots.prepend\"\n name=\"prepend\"\n />\n <div\n v-else-if=\"prependIcon\"\n :class=\"ui.icon()\"\n >\n <RuiIcon\n :name=\"prependIcon\"\n :size=\"18\"\n />\n </div>\n </div>\n <div :class=\"ui.inputWrapper()\">\n <textarea\n v-if=\"autoGrow\"\n ref=\"textareaSizer\"\n :value=\"modelValue\"\n :class=\"ui.textareaSizer()\"\n :style=\"fieldStyles\"\n aria-hidden=\"true\"\n disabled\n readonly\n />\n <textarea\n :id=\"textareaId\"\n ref=\"textarea\"\n v-model=\"modelValue\"\n :placeholder=\"placeholder || ' '\"\n :class=\"ui.textarea()\"\n :style=\"fieldStyles\"\n :disabled=\"disabled\"\n :readonly=\"readonly\"\n :aria-invalid=\"hasError\"\n v-bind=\"getNonRootAttrs($attrs)\"\n />\n <fieldset :class=\"ui.fieldset()\" />\n </div>\n <div\n v-if=\"$slots.append || appendIcon || showClearIcon\"\n ref=\"append\"\n :class=\"ui.append()\"\n data-id=\"append\"\n >\n <RuiButton\n v-if=\"showClearIcon\"\n :class=\"[ui.clearButton(), { hidden: !showClearButton }]\"\n variant=\"text\"\n type=\"button\"\n icon\n data-id=\"clear-btn\"\n aria-label=\"Clear\"\n tabindex=\"-1\"\n @click.stop=\"clearIconClicked()\"\n >\n <RuiIcon\n name=\"lu-x\"\n size=\"16\"\n />\n </RuiButton>\n <slot\n v-if=\"$slots.append\"\n name=\"append\"\n />\n <div\n v-else-if=\"appendIcon\"\n :class=\"ui.icon()\"\n >\n <RuiIcon\n :name=\"appendIcon\"\n :size=\"18\"\n />\n </div>\n </div>\n </div>\n <RuiFormTextDetail\n v-if=\"!hideDetails\"\n :class=\"ui.details()\"\n :error-messages=\"errorMessages\"\n :success-messages=\"successMessages\"\n :hint=\"hint\"\n />\n </div>\n</template>\n"],"mappings":"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"}
1
+ {"version":3,"file":"RuiTextArea.vue_vue_type_script_setup_true_lang.js","names":["$attrs","$slots","_useModel","_openBlock","_createElementBlock","_normalizeProps","_guardReactiveProps","_unref","_createBlock","RuiFieldLabel","_createCommentVNode","_createElementVNode","_normalizeClass","_normalizeStyle","_renderSlot","_createVNode","RuiIcon","_withDirectives","_mergeProps","_vModelText","RuiButton","_withModifiers","_withCtx","RuiFormTextDetail"],"sources":["../../../../src/components/forms/text-area/RuiTextArea.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport type { ContextColorsType } from '@/consts/colors';\nimport type { RuiIcons } from '@/icons';\nimport RuiButton from '@/components/buttons/button/RuiButton.vue';\nimport RuiFieldLabel from '@/components/forms/field-label/RuiFieldLabel.vue';\nimport { textAreaStyles } from '@/components/forms/text-area/text-area-styles';\nimport RuiFormTextDetail from '@/components/helpers/RuiFormTextDetail.vue';\nimport RuiIcon from '@/components/icons/RuiIcon.vue';\nimport { type LabelPlacement, useLabelPlacement } from '@/composables/defaults/field';\nimport { usePrependAppendWidth } from '@/composables/forms/use-prepend-append-width';\nimport { useTimeoutManager } from '@/composables/timeout-manager';\nimport { type FormDetails, useFormDetails, useFormTextDetail } from '@/utils/form-text-detail';\nimport { getNonRootAttrs, getRootAttrs } from '@/utils/helpers';\n\nexport interface TextAreaProps {\n label?: string;\n placeholder?: string;\n disabled?: boolean;\n /** Where the label shows; falls back to the nearest `RuiFieldDefaults`, then the app default, then `top`. */\n labelPlacement?: LabelPlacement;\n color?: ContextColorsType;\n textColor?: ContextColorsType;\n dense?: boolean;\n hint?: string;\n errorMessages?: string | string[];\n successMessages?: string | string[];\n /** The line under the field for its hint and messages: `reserve`, `auto` or `hidden`; falls back to the nearest `RuiFieldDefaults`, then the app default, then `reserve`. */\n details?: FormDetails;\n /** @deprecated Use `details=\"hidden\"`. Removed in 4.0. */\n hideDetails?: boolean;\n prependIcon?: RuiIcons;\n appendIcon?: RuiIcons;\n readonly?: boolean;\n clearable?: boolean;\n noResize?: boolean;\n minRows?: number | string;\n maxRows?: number | string;\n rowHeight?: number | string;\n autoGrow?: boolean;\n required?: boolean;\n}\n\ndefineOptions({\n name: 'RuiTextArea',\n inheritAttrs: false,\n});\n\nconst modelValue = defineModel<string>({ required: true });\n\nconst {\n label = '',\n placeholder = '',\n disabled = false,\n labelPlacement = undefined,\n color = undefined,\n textColor = undefined,\n dense = false,\n hint = '',\n errorMessages = [],\n successMessages = [],\n details = undefined,\n hideDetails = false,\n prependIcon = undefined,\n appendIcon = undefined,\n readonly = false,\n clearable = false,\n noResize = false,\n minRows = 2,\n rowHeight = 1.5,\n maxRows = undefined,\n autoGrow = false,\n required = false,\n} = defineProps<TextAreaProps>();\n\nconst emit = defineEmits<{\n 'click:clear': [];\n}>();\n\ndefineSlots<{\n prepend?: () => any;\n append?: () => any;\n}>();\n\nconst isHovered = ref<boolean>(false);\nconst showClearButton = ref<boolean>(false);\n\nconst prepend = useTemplateRef<HTMLDivElement>('prepend');\nconst append = useTemplateRef<HTMLDivElement>('append');\nconst textarea = useTemplateRef<HTMLTextAreaElement>('textarea');\nconst textareaSizer = useTemplateRef<HTMLTextAreaElement>('textareaSizer');\n\nconst generatedId = useId();\nconst attrs = useAttrs();\n\nconst { focused } = useFocus(textarea);\nconst placement = useLabelPlacement(() => labelPlacement);\nconst { clear: cancelClearHide, create: delayClearHide } = useTimeoutManager();\nconst { prependWidth, appendWidth } = usePrependAppendWidth(prepend, append, 24);\nconst { hasError, hasSuccess, hasMessages, validation } = useFormTextDetail(\n () => errorMessages,\n () => successMessages,\n);\nconst detailsMode = useFormDetails(() => details, () => hideDetails);\n\nconst textareaId = computed<string>(() => {\n const id = attrs.id;\n return typeof id === 'string' && id ? id : generatedId;\n});\n\nconst showClearIcon = computed<boolean>(() => clearable && !!get(modelValue) && !disabled && !readonly);\n\nconst effectiveTextColor = computed<ContextColorsType | undefined>(() => {\n if (get(hasError))\n return 'error';\n if (get(hasSuccess))\n return 'success';\n if (textColor && !get(hasMessages))\n return textColor;\n return undefined;\n});\n\nconst effectiveColor = computed<ContextColorsType | undefined>(() => get(validation) ?? color);\n\nconst ui = computed<ReturnType<typeof textAreaStyles>>(() => textAreaStyles({\n dense,\n disabled,\n readonly,\n noResize,\n hovered: get(isHovered),\n focused: get(focused),\n color: get(effectiveColor),\n textColor: get(effectiveTextColor),\n validation: get(validation),\n}));\n\nconst wrapperStyle = computed<Record<string, string>>(() => ({\n '--prepend-w': get(prependWidth),\n '--append-w': get(appendWidth),\n}));\n\nconst fieldStyles = computed<{ minHeight: string; maxHeight?: string }>(() => {\n const height = Number(rowHeight);\n const min = Number(minRows);\n const max = Number(maxRows);\n const value: { minHeight: string; maxHeight?: string } = {\n minHeight: `${min * height + 0.75}rem`,\n };\n if (max)\n value.maxHeight = `${max * height + 0.75}rem`;\n\n return value;\n});\n\nfunction clearIconClicked(): void {\n set(modelValue, '');\n emit('click:clear');\n}\n\nfunction computeFieldHeight(newVal?: string, oldVal?: string): void {\n if (!autoGrow)\n return;\n\n const field = get(textarea);\n const fieldValue = newVal ?? get(modelValue);\n const fieldSizer = get(textareaSizer);\n if (!(field && fieldSizer))\n return;\n\n nextTick(() => {\n const sizerHeight = fieldSizer.scrollHeight;\n const fieldHeight = field.scrollHeight;\n let height = `${Math.max(sizerHeight, fieldHeight) / 16}rem`;\n if (oldVal && oldVal.length > fieldValue.length)\n height = `${Math.min(sizerHeight, fieldHeight) / 16}rem`;\n\n field.style.height = height;\n });\n}\n\nwatch(focused, (value) => {\n if (value) {\n // a refocus within the delay keeps the button\n cancelClearHide();\n set(showClearButton, true);\n }\n else {\n delayClearHide(() => set(showClearButton, false), 500);\n }\n});\n\nwatchDebounced(modelValue, computeFieldHeight, { debounce: 50 });\n\nonMounted(computeFieldHeight);\n\ndefineExpose({\n focus: () => get(textarea)?.focus(),\n element: textarea,\n});\n</script>\n\n<template>\n <div v-bind=\"getRootAttrs($attrs)\">\n <RuiFieldLabel\n v-if=\"label\"\n :text=\"label\"\n :for=\"textareaId\"\n :hidden=\"placement === 'hidden'\"\n :required=\"required\"\n :disabled=\"disabled\"\n />\n <div\n :class=\"ui.wrapper()\"\n :style=\"wrapperStyle\"\n data-id=\"wrapper\"\n @mouseenter=\"isHovered = true\"\n @mouseleave=\"isHovered = false\"\n >\n <div\n v-if=\"$slots.prepend || prependIcon\"\n ref=\"prepend\"\n :class=\"ui.prepend()\"\n data-id=\"prepend\"\n >\n <slot\n v-if=\"$slots.prepend\"\n name=\"prepend\"\n />\n <div\n v-else-if=\"prependIcon\"\n :class=\"ui.icon()\"\n >\n <RuiIcon\n :name=\"prependIcon\"\n :size=\"18\"\n />\n </div>\n </div>\n <div :class=\"ui.inputWrapper()\">\n <textarea\n v-if=\"autoGrow\"\n ref=\"textareaSizer\"\n :value=\"modelValue\"\n :class=\"ui.textareaSizer()\"\n :style=\"fieldStyles\"\n aria-hidden=\"true\"\n disabled\n readonly\n />\n <textarea\n :id=\"textareaId\"\n ref=\"textarea\"\n v-model=\"modelValue\"\n :placeholder=\"placeholder || ' '\"\n :class=\"ui.textarea()\"\n :style=\"fieldStyles\"\n :disabled=\"disabled\"\n :readonly=\"readonly\"\n :aria-invalid=\"hasError\"\n v-bind=\"getNonRootAttrs($attrs)\"\n />\n <fieldset :class=\"ui.fieldset()\" />\n </div>\n <div\n v-if=\"$slots.append || appendIcon || showClearIcon\"\n ref=\"append\"\n :class=\"ui.append()\"\n data-id=\"append\"\n >\n <RuiButton\n v-if=\"showClearIcon\"\n :class=\"[ui.clearButton(), { hidden: !showClearButton }]\"\n variant=\"text\"\n type=\"button\"\n icon\n data-id=\"clear-btn\"\n aria-label=\"Clear\"\n tabindex=\"-1\"\n @click.stop=\"clearIconClicked()\"\n >\n <RuiIcon\n name=\"lu-x\"\n size=\"16\"\n />\n </RuiButton>\n <slot\n v-if=\"$slots.append\"\n name=\"append\"\n />\n <div\n v-else-if=\"appendIcon\"\n :class=\"ui.icon()\"\n >\n <RuiIcon\n :name=\"appendIcon\"\n :size=\"18\"\n />\n </div>\n </div>\n </div>\n <RuiFormTextDetail\n v-if=\"detailsMode !== 'hidden'\"\n :details=\"detailsMode\"\n :error-messages=\"errorMessages\"\n :success-messages=\"successMessages\"\n :hint=\"hint\"\n />\n </div>\n</template>\n"],"mappings":"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"}
@@ -78,7 +78,6 @@ export declare const textAreaStyles: import("tailwind-variants").TVReturnType<{
78
78
  prepend: string;
79
79
  append: string;
80
80
  icon: string;
81
- details: string;
82
81
  clearButton: string;
83
82
  }, undefined, {
84
83
  hovered: {
@@ -27,7 +27,6 @@ var textAreaStyles = tv({
27
27
  prepend: "flex items-center gap-1 shrink-0 h-6 mt-2 ml-3",
28
28
  append: "flex items-center gap-1 shrink-0 absolute right-0 h-6 mt-2 mr-3",
29
29
  icon: "text-rui-neutral-500 dark:text-rui-neutral-400",
30
- details: "pt-1",
31
30
  clearButton: ["!p-1 last:-mr-1", "text-rui-neutral-500 dark:text-rui-neutral-400 hover:text-rui-text dark:hover:text-rui-text"].join(" ")
32
31
  },
33
32
  variants: {
@@ -1 +1 @@
1
- {"version":3,"file":"text-area-styles.js","names":[],"sources":["../../../../src/components/forms/text-area/text-area-styles.ts"],"sourcesContent":["import { textInputBase } from '@/components/forms/text-input-styles';\nimport { tv } from '@/utils/tv';\n\n/**\n * tv() styles for RuiTextArea: an even 8px padding, 14px text and the text field's bordered\n * `fieldset`, focus and disabled treatment from textInputBase. The label sits above in\n * RuiFieldLabel, so the placeholder is always shown.\n *\n * The append area is absolutely placed, so the textarea reserves its width (`--append-w`) as right\n * padding.\n *\n * IMPORTANT: tv() extend does NOT deduplicate conflicting Tailwind classes between base and\n * extension, so the fieldset's classes live only in textInputBase.\n */\nexport const textAreaStyles = tv({\n extend: textInputBase,\n slots: {\n fieldset: '',\n wrapper: 'relative w-full min-w-[12.5rem] flex items-start rounded-rui-control bg-white dark:bg-transparent',\n inputWrapper: 'flex flex-1 pt-2',\n textarea: [\n 'peer w-full bg-transparent pt-0 pb-2 px-3 [padding-right:calc(0.75rem+var(--append-w,0px))]',\n 'text-sm/6 text-rui-text outline-hidden',\n 'placeholder:text-rui-neutral-500 dark:placeholder:text-rui-neutral-400',\n ].join(' '),\n textareaSizer: 'invisible absolute top-0 left-0 w-full h-0 -z-10 pointer-events-none px-3 text-sm',\n // both sides are one 24px line tall and start where the text does, so icons center on the first line\n prepend: 'flex items-center gap-1 shrink-0 h-6 mt-2 ml-3',\n append: 'flex items-center gap-1 shrink-0 absolute right-0 h-6 mt-2 mr-3',\n icon: 'text-rui-neutral-500 dark:text-rui-neutral-400',\n details: 'pt-1',\n // 24px round a 16px glyph; as the last control it pulls into the inset by its own padding\n clearButton: [\n '!p-1 last:-mr-1',\n 'text-rui-neutral-500 dark:text-rui-neutral-400 hover:text-rui-text dark:hover:text-rui-text',\n ].join(' '),\n },\n variants: {\n // 4px above and below the text rather than 8px, the 4px the dense text field drops\n dense: {\n true: {\n inputWrapper: 'pt-1',\n textarea: 'pb-1',\n textareaSizer: 'pb-1',\n prepend: 'mt-1',\n append: 'mt-1',\n },\n },\n noResize: {\n true: { textarea: 'resize-none' },\n false: { textarea: 'resize-y' },\n },\n // Icons keep the neutral tone; the color goes to the text around them\n textColor: {\n primary: { prepend: 'text-rui-primary', append: 'text-rui-primary', textarea: 'text-rui-primary' },\n secondary: { prepend: 'text-rui-secondary', append: 'text-rui-secondary', textarea: 'text-rui-secondary' },\n error: { prepend: 'text-rui-error', append: 'text-rui-error', textarea: 'text-rui-error' },\n warning: { prepend: 'text-rui-warning', append: 'text-rui-warning', textarea: 'text-rui-warning' },\n info: { prepend: 'text-rui-info', append: 'text-rui-info', textarea: 'text-rui-info' },\n success: { prepend: 'text-rui-success', append: 'text-rui-success', textarea: 'text-rui-success' },\n },\n disabled: {\n true: { wrapper: 'bg-rui-neutral-50 dark:bg-rui-neutral-900' },\n },\n // the activators' read-only fill, restated for dark over the base `dark:bg-transparent`\n readonly: {\n true: { wrapper: 'bg-rui-surface-muted dark:bg-rui-surface-muted' },\n },\n },\n defaultVariants: {\n noResize: false,\n },\n});\n"],"mappings":";;;;;;;;;;;;;;AAcA,IAAa,iBAAiB,GAAG;CAC/B,QAAQ;CACR,OAAO;EACL,UAAU;EACV,SAAS;EACT,cAAc;EACd,UAAU;GACR;GACA;GACA;EACF,CAAC,CAAC,KAAK,GAAG;EACV,eAAe;EAEf,SAAS;EACT,QAAQ;EACR,MAAM;EACN,SAAS;EAET,aAAa,CACX,mBACA,6FACF,CAAC,CAAC,KAAK,GAAG;CACZ;CACA,UAAU;EAER,OAAO,EACL,MAAM;GACJ,cAAc;GACd,UAAU;GACV,eAAe;GACf,SAAS;GACT,QAAQ;EACV,EACF;EACA,UAAU;GACR,MAAM,EAAE,UAAU,cAAc;GAChC,OAAO,EAAE,UAAU,WAAW;EAChC;EAEA,WAAW;GACT,SAAS;IAAE,SAAS;IAAoB,QAAQ;IAAoB,UAAU;GAAmB;GACjG,WAAW;IAAE,SAAS;IAAsB,QAAQ;IAAsB,UAAU;GAAqB;GACzG,OAAO;IAAE,SAAS;IAAkB,QAAQ;IAAkB,UAAU;GAAiB;GACzF,SAAS;IAAE,SAAS;IAAoB,QAAQ;IAAoB,UAAU;GAAmB;GACjG,MAAM;IAAE,SAAS;IAAiB,QAAQ;IAAiB,UAAU;GAAgB;GACrF,SAAS;IAAE,SAAS;IAAoB,QAAQ;IAAoB,UAAU;GAAmB;EACnG;EACA,UAAU,EACR,MAAM,EAAE,SAAS,4CAA4C,EAC/D;EAEA,UAAU,EACR,MAAM,EAAE,SAAS,iDAAiD,EACpE;CACF;CACA,iBAAiB,EACf,UAAU,MACZ;AACF,CAAC"}
1
+ {"version":3,"file":"text-area-styles.js","names":[],"sources":["../../../../src/components/forms/text-area/text-area-styles.ts"],"sourcesContent":["import { textInputBase } from '@/components/forms/text-input-styles';\nimport { tv } from '@/utils/tv';\n\n/**\n * tv() styles for RuiTextArea: an even 8px padding, 14px text and the text field's bordered\n * `fieldset`, focus and disabled treatment from textInputBase. The label sits above in\n * RuiFieldLabel, so the placeholder is always shown.\n *\n * The append area is absolutely placed, so the textarea reserves its width (`--append-w`) as right\n * padding.\n *\n * IMPORTANT: tv() extend does NOT deduplicate conflicting Tailwind classes between base and\n * extension, so the fieldset's classes live only in textInputBase.\n */\nexport const textAreaStyles = tv({\n extend: textInputBase,\n slots: {\n fieldset: '',\n wrapper: 'relative w-full min-w-[12.5rem] flex items-start rounded-rui-control bg-white dark:bg-transparent',\n inputWrapper: 'flex flex-1 pt-2',\n textarea: [\n 'peer w-full bg-transparent pt-0 pb-2 px-3 [padding-right:calc(0.75rem+var(--append-w,0px))]',\n 'text-sm/6 text-rui-text outline-hidden',\n 'placeholder:text-rui-neutral-500 dark:placeholder:text-rui-neutral-400',\n ].join(' '),\n textareaSizer: 'invisible absolute top-0 left-0 w-full h-0 -z-10 pointer-events-none px-3 text-sm',\n // both sides are one 24px line tall and start where the text does, so icons center on the first line\n prepend: 'flex items-center gap-1 shrink-0 h-6 mt-2 ml-3',\n append: 'flex items-center gap-1 shrink-0 absolute right-0 h-6 mt-2 mr-3',\n icon: 'text-rui-neutral-500 dark:text-rui-neutral-400',\n // 24px round a 16px glyph; as the last control it pulls into the inset by its own padding\n clearButton: [\n '!p-1 last:-mr-1',\n 'text-rui-neutral-500 dark:text-rui-neutral-400 hover:text-rui-text dark:hover:text-rui-text',\n ].join(' '),\n },\n variants: {\n // 4px above and below the text rather than 8px, the 4px the dense text field drops\n dense: {\n true: {\n inputWrapper: 'pt-1',\n textarea: 'pb-1',\n textareaSizer: 'pb-1',\n prepend: 'mt-1',\n append: 'mt-1',\n },\n },\n noResize: {\n true: { textarea: 'resize-none' },\n false: { textarea: 'resize-y' },\n },\n // Icons keep the neutral tone; the color goes to the text around them\n textColor: {\n primary: { prepend: 'text-rui-primary', append: 'text-rui-primary', textarea: 'text-rui-primary' },\n secondary: { prepend: 'text-rui-secondary', append: 'text-rui-secondary', textarea: 'text-rui-secondary' },\n error: { prepend: 'text-rui-error', append: 'text-rui-error', textarea: 'text-rui-error' },\n warning: { prepend: 'text-rui-warning', append: 'text-rui-warning', textarea: 'text-rui-warning' },\n info: { prepend: 'text-rui-info', append: 'text-rui-info', textarea: 'text-rui-info' },\n success: { prepend: 'text-rui-success', append: 'text-rui-success', textarea: 'text-rui-success' },\n },\n disabled: {\n true: { wrapper: 'bg-rui-neutral-50 dark:bg-rui-neutral-900' },\n },\n // the activators' read-only fill, restated for dark over the base `dark:bg-transparent`\n readonly: {\n true: { wrapper: 'bg-rui-surface-muted dark:bg-rui-surface-muted' },\n },\n },\n defaultVariants: {\n noResize: false,\n },\n});\n"],"mappings":";;;;;;;;;;;;;;AAcA,IAAa,iBAAiB,GAAG;CAC/B,QAAQ;CACR,OAAO;EACL,UAAU;EACV,SAAS;EACT,cAAc;EACd,UAAU;GACR;GACA;GACA;EACF,CAAC,CAAC,KAAK,GAAG;EACV,eAAe;EAEf,SAAS;EACT,QAAQ;EACR,MAAM;EAEN,aAAa,CACX,mBACA,6FACF,CAAC,CAAC,KAAK,GAAG;CACZ;CACA,UAAU;EAER,OAAO,EACL,MAAM;GACJ,cAAc;GACd,UAAU;GACV,eAAe;GACf,SAAS;GACT,QAAQ;EACV,EACF;EACA,UAAU;GACR,MAAM,EAAE,UAAU,cAAc;GAChC,OAAO,EAAE,UAAU,WAAW;EAChC;EAEA,WAAW;GACT,SAAS;IAAE,SAAS;IAAoB,QAAQ;IAAoB,UAAU;GAAmB;GACjG,WAAW;IAAE,SAAS;IAAsB,QAAQ;IAAsB,UAAU;GAAqB;GACzG,OAAO;IAAE,SAAS;IAAkB,QAAQ;IAAkB,UAAU;GAAiB;GACzF,SAAS;IAAE,SAAS;IAAoB,QAAQ;IAAoB,UAAU;GAAmB;GACjG,MAAM;IAAE,SAAS;IAAiB,QAAQ;IAAiB,UAAU;GAAgB;GACrF,SAAS;IAAE,SAAS;IAAoB,QAAQ;IAAoB,UAAU;GAAmB;EACnG;EACA,UAAU,EACR,MAAM,EAAE,SAAS,4CAA4C,EAC/D;EAEA,UAAU,EACR,MAAM,EAAE,SAAS,iDAAiD,EACpE;CACF;CACA,iBAAiB,EACf,UAAU,MACZ;AACF,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"RuiTextField.js","names":["_sfc_main"],"sources":["../../../../src/components/forms/text-field/RuiTextField.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport type { ContextColorsType } from '@/consts/colors';\nimport type { RuiIcons } from '@/icons';\nimport RuiButton from '@/components/buttons/button/RuiButton.vue';\nimport RuiFieldLabel from '@/components/forms/field-label/RuiFieldLabel.vue';\nimport { textFieldStyles } from '@/components/forms/text-field/text-field-styles';\nimport RuiFormTextDetail from '@/components/helpers/RuiFormTextDetail.vue';\nimport RuiIcon from '@/components/icons/RuiIcon.vue';\nimport { type LabelPlacement, useLabelPlacement } from '@/composables/defaults/field';\nimport { useTimeoutManager } from '@/composables/timeout-manager';\nimport { useFormTextDetail } from '@/utils/form-text-detail';\nimport { getNonRootAttrs, getRootAttrs } from '@/utils/helpers';\n\nexport interface TextFieldProps {\n label?: string;\n placeholder?: string;\n disabled?: boolean;\n /** Where the label shows; falls back to the nearest `RuiFieldDefaults`, then the app default, then `top`. */\n labelPlacement?: LabelPlacement;\n color?: ContextColorsType;\n textColor?: ContextColorsType;\n dense?: boolean;\n hint?: string;\n errorMessages?: string | string[];\n successMessages?: string | string[];\n hideDetails?: boolean;\n prependIcon?: RuiIcons;\n appendIcon?: RuiIcons;\n readonly?: boolean;\n clearable?: boolean;\n required?: boolean;\n}\n\ndefineOptions({\n name: 'RuiTextField',\n inheritAttrs: false,\n});\n\nconst modelValue = defineModel<string>({ required: true });\n\nconst {\n label = '',\n placeholder = '',\n disabled = false,\n labelPlacement = undefined,\n color = undefined,\n textColor = undefined,\n dense = false,\n hint = '',\n errorMessages = [],\n successMessages = [],\n hideDetails = false,\n prependIcon = undefined,\n appendIcon = undefined,\n readonly = false,\n clearable = false,\n required = false,\n} = defineProps<TextFieldProps>();\n\nconst emit = defineEmits<{\n 'focus-input': [event: Event];\n 'blur': [event: Event];\n 'remove': [value: unknown];\n 'clear': [];\n}>();\n\ndefineSlots<{\n prepend?: () => any;\n append?: () => any;\n /** Rich hint content under the field, in place of the `hint` text; error and success messages still take precedence. */\n hint?: () => any;\n}>();\n\nconst isHovered = ref<boolean>(false);\nconst showClearButton = ref<boolean>(false);\n\nconst inputRef = useTemplateRef<HTMLInputElement>('inputRef');\n\nconst generatedId = useId();\nconst attrs = useAttrs();\n\nconst { focused } = useFocus(inputRef);\nconst placement = useLabelPlacement(() => labelPlacement);\nconst { clear: cancelClearHide, create: delayClearHide } = useTimeoutManager();\nconst { hasError, hasSuccess, hasMessages, validation } = useFormTextDetail(\n () => errorMessages,\n () => successMessages,\n);\n\nconst inputId = computed<string>(() => {\n const id = attrs.id;\n return typeof id === 'string' && id ? id : generatedId;\n});\n\nconst showClearIcon = computed<boolean>(() => clearable && !!get(modelValue) && !disabled && !readonly);\n\nconst effectiveTextColor = computed<ContextColorsType | undefined>(() => {\n if (get(hasError))\n return 'error';\n if (get(hasSuccess))\n return 'success';\n if (textColor && !get(hasMessages))\n return textColor;\n return undefined;\n});\n\nconst effectiveColor = computed<ContextColorsType | undefined>(() => get(validation) ?? color);\n\nconst ui = computed<ReturnType<typeof textFieldStyles>>(() => textFieldStyles({\n dense,\n disabled,\n readonly,\n hovered: get(isHovered),\n focused: get(focused),\n color: get(effectiveColor),\n textColor: get(effectiveTextColor),\n validation: get(validation),\n}));\n\nfunction input(event: Event): void {\n const target = event.target;\n if (target instanceof HTMLInputElement) {\n set(modelValue, target.value);\n }\n}\n\nfunction clearIconClicked(): void {\n set(modelValue, '');\n emit('clear');\n}\n\nwatch(focused, (value) => {\n if (value) {\n // a refocus within the delay keeps the button\n cancelClearHide();\n set(showClearButton, true);\n }\n else {\n delayClearHide(() => set(showClearButton, false), 500);\n }\n});\n\ndefineExpose({\n setSelectionRange: (start: number, end: number) => {\n get(inputRef)?.setSelectionRange(start, end);\n },\n focus: () => get(inputRef)?.focus(),\n element: inputRef,\n});\n</script>\n\n<template>\n <div v-bind=\"getRootAttrs($attrs)\">\n <RuiFieldLabel\n v-if=\"label\"\n :text=\"label\"\n :for=\"inputId\"\n :hidden=\"placement === 'hidden'\"\n :required=\"required\"\n :disabled=\"disabled\"\n />\n <div\n :class=\"ui.wrapper()\"\n data-id=\"wrapper\"\n @mouseenter=\"isHovered = true\"\n @mouseleave=\"isHovered = false\"\n >\n <div\n v-if=\"$slots.prepend || prependIcon\"\n :class=\"ui.prepend()\"\n data-id=\"prepend\"\n >\n <slot\n v-if=\"$slots.prepend\"\n name=\"prepend\"\n />\n <div\n v-else-if=\"prependIcon\"\n :class=\"ui.icon()\"\n >\n <RuiIcon\n :name=\"prependIcon\"\n :size=\"18\"\n />\n </div>\n </div>\n <div\n :class=\"ui.inputWrapper()\"\n @click=\"emit('focus-input', $event)\"\n >\n <input\n :id=\"inputId\"\n ref=\"inputRef\"\n :value=\"modelValue\"\n :placeholder=\"placeholder || ' '\"\n :class=\"ui.input()\"\n :disabled=\"disabled\"\n :readonly=\"readonly\"\n :aria-invalid=\"hasError\"\n v-bind=\"getNonRootAttrs($attrs)\"\n @input=\"input($event)\"\n @blur=\"emit('blur', $event)\"\n @remove=\"emit('remove', $event)\"\n />\n <fieldset :class=\"ui.fieldset()\" />\n </div>\n <div\n v-if=\"$slots.append || appendIcon || showClearIcon\"\n :class=\"ui.append()\"\n data-id=\"append\"\n >\n <RuiButton\n v-if=\"showClearIcon\"\n :class=\"[ui.clearButton(), { hidden: !showClearButton }]\"\n variant=\"text\"\n type=\"button\"\n icon\n data-id=\"clear-btn\"\n aria-label=\"Clear\"\n tabindex=\"-1\"\n @click.stop=\"clearIconClicked()\"\n >\n <RuiIcon\n name=\"lu-x\"\n size=\"16\"\n />\n </RuiButton>\n <slot\n v-if=\"$slots.append\"\n name=\"append\"\n />\n <div\n v-else-if=\"appendIcon\"\n :class=\"ui.icon()\"\n >\n <RuiIcon\n :name=\"appendIcon\"\n :size=\"18\"\n />\n </div>\n </div>\n </div>\n <RuiFormTextDetail\n v-if=\"!hideDetails\"\n :class=\"ui.details()\"\n :error-messages=\"errorMessages\"\n :success-messages=\"successMessages\"\n :hint=\"hint\"\n >\n <template\n v-if=\"$slots.hint\"\n #hint\n >\n <slot name=\"hint\" />\n </template>\n </RuiFormTextDetail>\n </div>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"RuiTextField.js","names":["_sfc_main"],"sources":["../../../../src/components/forms/text-field/RuiTextField.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport type { ContextColorsType } from '@/consts/colors';\nimport type { RuiIcons } from '@/icons';\nimport RuiButton from '@/components/buttons/button/RuiButton.vue';\nimport RuiFieldLabel from '@/components/forms/field-label/RuiFieldLabel.vue';\nimport { textFieldStyles } from '@/components/forms/text-field/text-field-styles';\nimport RuiFormTextDetail from '@/components/helpers/RuiFormTextDetail.vue';\nimport RuiIcon from '@/components/icons/RuiIcon.vue';\nimport { type LabelPlacement, useLabelPlacement } from '@/composables/defaults/field';\nimport { useTimeoutManager } from '@/composables/timeout-manager';\nimport { type FormDetails, useFormDetails, useFormTextDetail } from '@/utils/form-text-detail';\nimport { getNonRootAttrs, getRootAttrs } from '@/utils/helpers';\n\nexport interface TextFieldProps {\n label?: string;\n placeholder?: string;\n disabled?: boolean;\n /** Where the label shows; falls back to the nearest `RuiFieldDefaults`, then the app default, then `top`. */\n labelPlacement?: LabelPlacement;\n color?: ContextColorsType;\n textColor?: ContextColorsType;\n dense?: boolean;\n hint?: string;\n errorMessages?: string | string[];\n successMessages?: string | string[];\n /** The line under the field for its hint and messages: `reserve`, `auto` or `hidden`; falls back to the nearest `RuiFieldDefaults`, then the app default, then `reserve`. */\n details?: FormDetails;\n /** @deprecated Use `details=\"hidden\"`. Removed in 4.0. */\n hideDetails?: boolean;\n prependIcon?: RuiIcons;\n appendIcon?: RuiIcons;\n readonly?: boolean;\n clearable?: boolean;\n required?: boolean;\n}\n\ndefineOptions({\n name: 'RuiTextField',\n inheritAttrs: false,\n});\n\nconst modelValue = defineModel<string>({ required: true });\n\nconst {\n label = '',\n placeholder = '',\n disabled = false,\n labelPlacement = undefined,\n color = undefined,\n textColor = undefined,\n dense = false,\n hint = '',\n errorMessages = [],\n successMessages = [],\n details = undefined,\n hideDetails = false,\n prependIcon = undefined,\n appendIcon = undefined,\n readonly = false,\n clearable = false,\n required = false,\n} = defineProps<TextFieldProps>();\n\nconst emit = defineEmits<{\n 'focus-input': [event: Event];\n 'blur': [event: Event];\n 'remove': [value: unknown];\n 'clear': [];\n}>();\n\ndefineSlots<{\n prepend?: () => any;\n append?: () => any;\n /** Rich hint content under the field, in place of the `hint` text; error and success messages still take precedence. */\n hint?: () => any;\n}>();\n\nconst isHovered = ref<boolean>(false);\nconst showClearButton = ref<boolean>(false);\n\nconst inputRef = useTemplateRef<HTMLInputElement>('inputRef');\n\nconst generatedId = useId();\nconst attrs = useAttrs();\n\nconst { focused } = useFocus(inputRef);\nconst placement = useLabelPlacement(() => labelPlacement);\nconst { clear: cancelClearHide, create: delayClearHide } = useTimeoutManager();\nconst { hasError, hasSuccess, hasMessages, validation } = useFormTextDetail(\n () => errorMessages,\n () => successMessages,\n);\nconst detailsMode = useFormDetails(() => details, () => hideDetails);\n\nconst inputId = computed<string>(() => {\n const id = attrs.id;\n return typeof id === 'string' && id ? id : generatedId;\n});\n\nconst showClearIcon = computed<boolean>(() => clearable && !!get(modelValue) && !disabled && !readonly);\n\nconst effectiveTextColor = computed<ContextColorsType | undefined>(() => {\n if (get(hasError))\n return 'error';\n if (get(hasSuccess))\n return 'success';\n if (textColor && !get(hasMessages))\n return textColor;\n return undefined;\n});\n\nconst effectiveColor = computed<ContextColorsType | undefined>(() => get(validation) ?? color);\n\nconst ui = computed<ReturnType<typeof textFieldStyles>>(() => textFieldStyles({\n dense,\n disabled,\n readonly,\n hovered: get(isHovered),\n focused: get(focused),\n color: get(effectiveColor),\n textColor: get(effectiveTextColor),\n validation: get(validation),\n}));\n\nfunction input(event: Event): void {\n const target = event.target;\n if (target instanceof HTMLInputElement) {\n set(modelValue, target.value);\n }\n}\n\nfunction clearIconClicked(): void {\n set(modelValue, '');\n emit('clear');\n}\n\nwatch(focused, (value) => {\n if (value) {\n // a refocus within the delay keeps the button\n cancelClearHide();\n set(showClearButton, true);\n }\n else {\n delayClearHide(() => set(showClearButton, false), 500);\n }\n});\n\ndefineExpose({\n setSelectionRange: (start: number, end: number) => {\n get(inputRef)?.setSelectionRange(start, end);\n },\n focus: () => get(inputRef)?.focus(),\n element: inputRef,\n});\n</script>\n\n<template>\n <div v-bind=\"getRootAttrs($attrs)\">\n <RuiFieldLabel\n v-if=\"label\"\n :text=\"label\"\n :for=\"inputId\"\n :hidden=\"placement === 'hidden'\"\n :required=\"required\"\n :disabled=\"disabled\"\n />\n <div\n :class=\"ui.wrapper()\"\n data-id=\"wrapper\"\n @mouseenter=\"isHovered = true\"\n @mouseleave=\"isHovered = false\"\n >\n <div\n v-if=\"$slots.prepend || prependIcon\"\n :class=\"ui.prepend()\"\n data-id=\"prepend\"\n >\n <slot\n v-if=\"$slots.prepend\"\n name=\"prepend\"\n />\n <div\n v-else-if=\"prependIcon\"\n :class=\"ui.icon()\"\n >\n <RuiIcon\n :name=\"prependIcon\"\n :size=\"18\"\n />\n </div>\n </div>\n <div\n :class=\"ui.inputWrapper()\"\n @click=\"emit('focus-input', $event)\"\n >\n <input\n :id=\"inputId\"\n ref=\"inputRef\"\n :value=\"modelValue\"\n :placeholder=\"placeholder || ' '\"\n :class=\"ui.input()\"\n :disabled=\"disabled\"\n :readonly=\"readonly\"\n :aria-invalid=\"hasError\"\n v-bind=\"getNonRootAttrs($attrs)\"\n @input=\"input($event)\"\n @blur=\"emit('blur', $event)\"\n @remove=\"emit('remove', $event)\"\n />\n <fieldset :class=\"ui.fieldset()\" />\n </div>\n <div\n v-if=\"$slots.append || appendIcon || showClearIcon\"\n :class=\"ui.append()\"\n data-id=\"append\"\n >\n <RuiButton\n v-if=\"showClearIcon\"\n :class=\"[ui.clearButton(), { hidden: !showClearButton }]\"\n variant=\"text\"\n type=\"button\"\n icon\n data-id=\"clear-btn\"\n aria-label=\"Clear\"\n tabindex=\"-1\"\n @click.stop=\"clearIconClicked()\"\n >\n <RuiIcon\n name=\"lu-x\"\n size=\"16\"\n />\n </RuiButton>\n <slot\n v-if=\"$slots.append\"\n name=\"append\"\n />\n <div\n v-else-if=\"appendIcon\"\n :class=\"ui.icon()\"\n >\n <RuiIcon\n :name=\"appendIcon\"\n :size=\"18\"\n />\n </div>\n </div>\n </div>\n <RuiFormTextDetail\n v-if=\"detailsMode !== 'hidden'\"\n :details=\"detailsMode\"\n :error-messages=\"errorMessages\"\n :success-messages=\"successMessages\"\n :hint=\"hint\"\n >\n <template\n v-if=\"$slots.hint\"\n #hint\n >\n <slot name=\"hint\" />\n </template>\n </RuiFormTextDetail>\n </div>\n</template>\n"],"mappings":""}