@rotki/ui-library 3.0.0 → 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.
- package/dist/components/accordions/accordion/RuiAccordion.js.map +1 -1
- package/dist/components/accordions/accordion/RuiAccordion.vue_vue_type_script_setup_true_lang.js +13 -2
- package/dist/components/accordions/accordion/RuiAccordion.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/alerts/RuiAlert.vue.d.ts +2 -2
- package/dist/components/buttons/button/RuiButton.js.map +1 -1
- package/dist/components/buttons/button/RuiButton.vue.d.ts +7 -1
- package/dist/components/buttons/button/RuiButton.vue_vue_type_script_setup_true_lang.js +4 -2
- package/dist/components/buttons/button/RuiButton.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/buttons/button/button-props.d.ts +3 -0
- package/dist/components/buttons/button/button-props.js +2 -1
- package/dist/components/buttons/button/button-props.js.map +1 -1
- package/dist/components/buttons/button/button-styles.d.ts +75 -0
- package/dist/components/buttons/button/button-styles.js +135 -4
- package/dist/components/buttons/button/button-styles.js.map +1 -1
- package/dist/components/cards/RuiCard.js.map +1 -1
- package/dist/components/cards/RuiCard.vue.d.ts +6 -0
- package/dist/components/cards/RuiCard.vue_vue_type_script_setup_true_lang.js +14 -2
- package/dist/components/cards/RuiCard.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/chips/RuiChip.js.map +1 -1
- package/dist/components/chips/RuiChip.vue_vue_type_script_setup_true_lang.js +14 -0
- package/dist/components/chips/RuiChip.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/chips/chip-props.d.ts +2 -0
- package/dist/components/chips/chip-props.js +3 -0
- package/dist/components/chips/chip-props.js.map +1 -1
- package/dist/components/color-picker/RuiColorInput.js.map +1 -1
- package/dist/components/color-picker/RuiColorInput.vue_vue_type_script_setup_true_lang.js +2 -2
- package/dist/components/color-picker/RuiColorInput.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/date-time-picker/RuiDateTimePicker.js.map +1 -1
- package/dist/components/date-time-picker/RuiDateTimePicker.vue.d.ts +4 -0
- package/dist/components/date-time-picker/RuiDateTimePicker.vue_vue_type_script_setup_true_lang.js +6 -2
- package/dist/components/date-time-picker/RuiDateTimePicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/date-time-picker/RuiDateTimePickerMenu.js.map +1 -1
- package/dist/components/date-time-picker/RuiDateTimePickerMenu.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/components/date-time-picker/RuiDateTimePickerMenu.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/date-time-picker/RuiTimezoneSelect.js.map +1 -1
- package/dist/components/date-time-picker/RuiTimezoneSelect.vue.d.ts +4 -0
- package/dist/components/date-time-picker/RuiTimezoneSelect.vue_vue_type_script_setup_true_lang.js +3 -2
- package/dist/components/date-time-picker/RuiTimezoneSelect.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/forms/auto-complete/RuiAutoComplete.js.map +1 -1
- package/dist/components/forms/auto-complete/RuiAutoComplete.vue_vue_type_script_setup_true_lang.js +6 -2
- package/dist/components/forms/auto-complete/RuiAutoComplete.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/forms/auto-complete/auto-complete-props.d.ts +4 -0
- package/dist/components/forms/category-picker/RuiCategoryPicker.js.map +1 -1
- package/dist/components/forms/category-picker/RuiCategoryPicker.vue.d.ts +4 -1
- package/dist/components/forms/category-picker/RuiCategoryPicker.vue_vue_type_script_setup_true_lang.js +7 -4
- package/dist/components/forms/category-picker/RuiCategoryPicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/forms/check-control-styles.d.ts +27 -0
- package/dist/components/forms/check-control-styles.js +26 -1
- package/dist/components/forms/check-control-styles.js.map +1 -1
- package/dist/components/forms/checkbox/RuiCheckbox.js.map +1 -1
- package/dist/components/forms/checkbox/RuiCheckbox.vue.d.ts +6 -0
- package/dist/components/forms/checkbox/RuiCheckbox.vue_vue_type_script_setup_true_lang.js +14 -4
- package/dist/components/forms/checkbox/RuiCheckbox.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/forms/checkbox/checkbox-group/RuiCheckboxGroup.js.map +1 -1
- package/dist/components/forms/checkbox/checkbox-group/RuiCheckboxGroup.vue.d.ts +4 -0
- package/dist/components/forms/checkbox/checkbox-group/RuiCheckboxGroup.vue_vue_type_script_setup_true_lang.js +7 -2
- package/dist/components/forms/checkbox/checkbox-group/RuiCheckboxGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/forms/field-defaults/RuiFieldDefaults.js.map +1 -1
- package/dist/components/forms/field-defaults/RuiFieldDefaults.vue.d.ts +3 -0
- package/dist/components/forms/field-defaults/RuiFieldDefaults.vue_vue_type_script_setup_true_lang.js +8 -2
- package/dist/components/forms/field-defaults/RuiFieldDefaults.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/forms/file-upload/RuiFileUpload.js.map +1 -1
- package/dist/components/forms/file-upload/RuiFileUpload.vue.d.ts +4 -1
- package/dist/components/forms/file-upload/RuiFileUpload.vue_vue_type_script_setup_true_lang.js +10 -3
- package/dist/components/forms/file-upload/RuiFileUpload.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/forms/radio-button/radio/RuiRadio.js.map +1 -1
- package/dist/components/forms/radio-button/radio/RuiRadio.vue.d.ts +6 -0
- package/dist/components/forms/radio-button/radio/RuiRadio.vue_vue_type_script_setup_true_lang.js +14 -3
- package/dist/components/forms/radio-button/radio/RuiRadio.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/forms/radio-button/radio-group/RuiRadioGroup.js.map +1 -1
- package/dist/components/forms/radio-button/radio-group/RuiRadioGroup.vue.d.ts +4 -0
- package/dist/components/forms/radio-button/radio-group/RuiRadioGroup.vue_vue_type_script_setup_true_lang.js +7 -2
- package/dist/components/forms/radio-button/radio-group/RuiRadioGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/forms/revealable-text-field/RuiRevealableTextField.js.map +1 -1
- package/dist/components/forms/revealable-text-field/RuiRevealableTextField.vue_vue_type_script_setup_true_lang.js +3 -2
- package/dist/components/forms/revealable-text-field/RuiRevealableTextField.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/forms/select/RuiMenuSelect.js.map +1 -1
- package/dist/components/forms/select/RuiMenuSelect.vue.d.ts +4 -0
- package/dist/components/forms/select/RuiMenuSelect.vue_vue_type_script_setup_true_lang.js +6 -2
- package/dist/components/forms/select/RuiMenuSelect.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/forms/slider/RuiSlider.js.map +1 -1
- package/dist/components/forms/slider/RuiSlider.vue.d.ts +4 -0
- package/dist/components/forms/slider/RuiSlider.vue_vue_type_script_setup_true_lang.js +6 -3
- package/dist/components/forms/slider/RuiSlider.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/forms/switch/RuiSwitch.js.map +1 -1
- package/dist/components/forms/switch/RuiSwitch.vue.d.ts +6 -0
- package/dist/components/forms/switch/RuiSwitch.vue_vue_type_script_setup_true_lang.js +25 -5
- package/dist/components/forms/switch/RuiSwitch.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/forms/text-area/RuiTextArea.js.map +1 -1
- package/dist/components/forms/text-area/RuiTextArea.vue.d.ts +4 -0
- package/dist/components/forms/text-area/RuiTextArea.vue_vue_type_script_setup_true_lang.js +6 -4
- package/dist/components/forms/text-area/RuiTextArea.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/forms/text-area/text-area-styles.d.ts +0 -1
- package/dist/components/forms/text-area/text-area-styles.js +0 -1
- package/dist/components/forms/text-area/text-area-styles.js.map +1 -1
- package/dist/components/forms/text-field/RuiTextField.js.map +1 -1
- package/dist/components/forms/text-field/RuiTextField.vue.d.ts +6 -2
- package/dist/components/forms/text-field/RuiTextField.vue_vue_type_script_setup_true_lang.js +6 -4
- package/dist/components/forms/text-field/RuiTextField.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/forms/text-field/text-field-styles.d.ts +0 -1
- package/dist/components/forms/text-field/text-field-styles.js +0 -1
- package/dist/components/forms/text-field/text-field-styles.js.map +1 -1
- package/dist/components/helpers/RuiFormTextDetail.js.map +1 -1
- package/dist/components/helpers/RuiFormTextDetail.vue.d.ts +14 -0
- package/dist/components/helpers/RuiFormTextDetail.vue_vue_type_script_setup_true_lang.js +41 -11
- package/dist/components/helpers/RuiFormTextDetail.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/loaders/RuiSkeletonBase.js.map +1 -1
- package/dist/components/loaders/RuiSkeletonBase.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/overlays/menu/RuiMenu.js.map +1 -1
- package/dist/components/overlays/menu/RuiMenu.vue.d.ts +3 -0
- package/dist/components/overlays/menu/RuiMenu.vue_vue_type_script_setup_true_lang.js +9 -1
- package/dist/components/overlays/menu/RuiMenu.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/tables/RuiDataTable.js.map +1 -1
- package/dist/components/tables/RuiDataTable.vue.d.ts +4 -0
- package/dist/components/tables/RuiDataTable.vue_vue_type_script_setup_true_lang.js +7 -1
- package/dist/components/tables/RuiDataTable.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/tables/RuiExpandButton.js.map +1 -1
- package/dist/components/tables/RuiExpandButton.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/tables/RuiTableHead.js.map +1 -1
- package/dist/components/tables/RuiTableHead.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/components/tables/RuiTableHead.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/tables/RuiTablePagination.js.map +1 -1
- package/dist/components/tables/RuiTablePagination.vue_vue_type_script_setup_true_lang.js +3 -3
- package/dist/components/tables/RuiTablePagination.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/tables/data-table/RuiDataTableAppendRow.js.map +1 -1
- package/dist/components/tables/data-table/RuiDataTableAppendRow.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/tables/data-table/RuiDataTableRow.js.map +1 -1
- package/dist/components/tables/data-table/RuiDataTableRow.vue_vue_type_script_setup_true_lang.js +2 -2
- package/dist/components/tables/data-table/RuiDataTableRow.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/tables/data-table-styles.d.ts +6 -0
- package/dist/components/tables/data-table-styles.js +11 -3
- package/dist/components/tables/data-table-styles.js.map +1 -1
- package/dist/components/tabs/tab-items/RuiTabItems.js.map +1 -1
- package/dist/components/tabs/tab-items/RuiTabItems.vue_vue_type_script_setup_true_lang.js +9 -2
- package/dist/components/tabs/tab-items/RuiTabItems.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/composables/clip-while-resizing.d.ts +15 -0
- package/dist/composables/clip-while-resizing.js +46 -0
- package/dist/composables/clip-while-resizing.js.map +1 -0
- package/dist/composables/defaults/field.d.ts +19 -3
- package/dist/composables/defaults/field.js +32 -6
- package/dist/composables/defaults/field.js.map +1 -1
- package/dist/composables/sticky-blocker.d.ts +20 -0
- package/dist/composables/sticky-blocker.js +62 -0
- package/dist/composables/sticky-blocker.js.map +1 -0
- package/dist/index.d.ts +6 -2
- package/dist/index.js.map +1 -1
- package/dist/style.css +275 -0
- package/dist/utils/development.d.ts +6 -0
- package/dist/utils/development.js +17 -0
- package/dist/utils/development.js.map +1 -0
- package/dist/utils/form-text-detail.d.ts +15 -0
- package/dist/utils/form-text-detail.js +11 -1
- package/dist/utils/form-text-detail.js.map +1 -1
- package/dist/web-types.json +232 -3
- package/package.json +1 -1
|
@@ -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=\"
|
|
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
|
-
|
|
252
|
+
unref(detailsMode) !== "hidden" ? (openBlock(), createBlock(RuiFormTextDetail_default, {
|
|
251
253
|
key: 1,
|
|
252
|
-
|
|
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
|
-
"
|
|
259
|
+
"details",
|
|
258
260
|
"error-messages",
|
|
259
261
|
"success-messages",
|
|
260
262
|
"hint"
|
package/dist/components/forms/text-area/RuiTextArea.vue_vue_type_script_setup_true_lang.js.map
CHANGED
|
@@ -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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"}
|
|
@@ -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
|
|
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=\"
|
|
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":""}
|
|
@@ -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 TextFieldProps {
|
|
5
6
|
label?: string;
|
|
6
7
|
placeholder?: string;
|
|
@@ -13,6 +14,9 @@ export interface TextFieldProps {
|
|
|
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;
|
|
@@ -39,14 +43,14 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {
|
|
|
39
43
|
clear: () => any;
|
|
40
44
|
"update:modelValue": (value: string) => any;
|
|
41
45
|
blur: (event: Event) => any;
|
|
42
|
-
"focus-input": (event: Event) => any;
|
|
43
46
|
remove: (value: unknown) => any;
|
|
47
|
+
"focus-input": (event: Event) => any;
|
|
44
48
|
}, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
|
|
45
49
|
onClear?: (() => any) | undefined;
|
|
46
50
|
"onUpdate:modelValue"?: ((value: string) => any) | undefined;
|
|
47
51
|
onBlur?: ((event: Event) => any) | undefined;
|
|
48
|
-
"onFocus-input"?: ((event: Event) => any) | undefined;
|
|
49
52
|
onRemove?: ((value: unknown) => any) | undefined;
|
|
53
|
+
"onFocus-input"?: ((event: Event) => any) | undefined;
|
|
50
54
|
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
51
55
|
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
52
56
|
declare const _default: typeof __VLS_export;
|
package/dist/components/forms/text-field/RuiTextField.vue_vue_type_script_setup_true_lang.js
CHANGED
|
@@ -3,7 +3,7 @@ import { get, set } from "../../../vendor/@vueuse/shared/dist/index.js";
|
|
|
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";
|
|
@@ -40,6 +40,7 @@ var RuiTextField_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ def
|
|
|
40
40
|
hint: { default: "" },
|
|
41
41
|
errorMessages: { default: () => [] },
|
|
42
42
|
successMessages: { default: () => [] },
|
|
43
|
+
details: { default: () => void 0 },
|
|
43
44
|
hideDetails: {
|
|
44
45
|
type: Boolean,
|
|
45
46
|
default: false
|
|
@@ -80,6 +81,7 @@ var RuiTextField_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ def
|
|
|
80
81
|
const placement = useLabelPlacement(() => __props.labelPlacement);
|
|
81
82
|
const { clear: cancelClearHide, create: delayClearHide } = useTimeoutManager();
|
|
82
83
|
const { hasError, hasSuccess, hasMessages, validation } = useFormTextDetail(() => __props.errorMessages, () => __props.successMessages);
|
|
84
|
+
const detailsMode = useFormDetails(() => __props.details, () => __props.hideDetails);
|
|
83
85
|
const inputId = computed(() => {
|
|
84
86
|
const id = attrs.id;
|
|
85
87
|
return typeof id === "string" && id ? id : generatedId;
|
|
@@ -201,9 +203,9 @@ var RuiTextField_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ def
|
|
|
201
203
|
size: 18
|
|
202
204
|
}, null, 8, ["name"])], 2)) : createCommentVNode("", true)], 2)) : createCommentVNode("", true)
|
|
203
205
|
], 34),
|
|
204
|
-
|
|
206
|
+
unref(detailsMode) !== "hidden" ? (openBlock(), createBlock(RuiFormTextDetail_default, {
|
|
205
207
|
key: 1,
|
|
206
|
-
|
|
208
|
+
details: unref(detailsMode),
|
|
207
209
|
"error-messages": __props.errorMessages,
|
|
208
210
|
"success-messages": __props.successMessages,
|
|
209
211
|
hint: __props.hint
|
|
@@ -212,7 +214,7 @@ var RuiTextField_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ def
|
|
|
212
214
|
fn: withCtx(() => [renderSlot(_ctx.$slots, "hint")]),
|
|
213
215
|
key: "0"
|
|
214
216
|
} : void 0]), 1032, [
|
|
215
|
-
"
|
|
217
|
+
"details",
|
|
216
218
|
"error-messages",
|
|
217
219
|
"success-messages",
|
|
218
220
|
"hint"
|
package/dist/components/forms/text-field/RuiTextField.vue_vue_type_script_setup_true_lang.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RuiTextField.vue_vue_type_script_setup_true_lang.js","names":["$attrs","$slots","_useModel","_openBlock","_createElementBlock","_normalizeProps","_guardReactiveProps","_unref","_createBlock","RuiFieldLabel","_createCommentVNode","_createElementVNode","_normalizeClass","_renderSlot","_createVNode","RuiIcon","_mergeProps","RuiButton","_withModifiers","_withCtx","RuiFormTextDetail","_createSlots"],"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":"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"}
|
|
1
|
+
{"version":3,"file":"RuiTextField.vue_vue_type_script_setup_true_lang.js","names":["$attrs","$slots","_useModel","_openBlock","_createElementBlock","_normalizeProps","_guardReactiveProps","_unref","_createBlock","RuiFieldLabel","_createCommentVNode","_createElementVNode","_normalizeClass","_renderSlot","_createVNode","RuiIcon","_mergeProps","RuiButton","_withModifiers","_withCtx","RuiFormTextDetail","_createSlots"],"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":"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"}
|
|
@@ -20,7 +20,6 @@ var textFieldStyles = tv({
|
|
|
20
20
|
prepend: "flex items-center gap-1 shrink-0 pl-3",
|
|
21
21
|
append: "flex items-center gap-1 shrink-0 pr-3",
|
|
22
22
|
icon: "text-rui-neutral-500 dark:text-rui-neutral-400",
|
|
23
|
-
details: "pt-1",
|
|
24
23
|
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(" ")
|
|
25
24
|
},
|
|
26
25
|
variants: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"text-field-styles.js","names":[],"sources":["../../../../src/components/forms/text-field/text-field-styles.ts"],"sourcesContent":["import { textInputBase } from '@/components/forms/text-input-styles';\nimport { tv } from '@/utils/tv';\n\n/**\n * tv() styles for RuiTextField: a 36px box (32px dense) with 14px text and the bordered `fieldset`\n * from textInputBase. The label sits above in RuiFieldLabel, so the placeholder is always shown.\n *\n * `text-sm/6` rather than `text-sm`: the bare class sets a 20px line, which makes a 32px box.\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 textFieldStyles = tv({\n extend: textInputBase,\n slots: {\n // Re-declare the base slot for type inference (extend merges classes at runtime)\n fieldset: '',\n wrapper: 'relative w-full flex items-center rounded-rui-control bg-white dark:bg-transparent',\n input: [\n 'peer w-full bg-transparent px-3 py-1.5 text-sm/6 text-rui-text outline-hidden',\n 'placeholder:text-rui-neutral-500 dark:placeholder:text-rui-neutral-400',\n ].join(' '),\n inputWrapper: 'flex flex-1',\n // matching insets: a glyph sits 12px from either edge\n prepend: 'flex items-center gap-1 shrink-0 pl-3',\n append: 'flex items-center gap-1 shrink-0 pr-3',\n icon: 'text-rui-neutral-500 dark:text-rui-neutral-400',\n
|
|
1
|
+
{"version":3,"file":"text-field-styles.js","names":[],"sources":["../../../../src/components/forms/text-field/text-field-styles.ts"],"sourcesContent":["import { textInputBase } from '@/components/forms/text-input-styles';\nimport { tv } from '@/utils/tv';\n\n/**\n * tv() styles for RuiTextField: a 36px box (32px dense) with 14px text and the bordered `fieldset`\n * from textInputBase. The label sits above in RuiFieldLabel, so the placeholder is always shown.\n *\n * `text-sm/6` rather than `text-sm`: the bare class sets a 20px line, which makes a 32px box.\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 textFieldStyles = tv({\n extend: textInputBase,\n slots: {\n // Re-declare the base slot for type inference (extend merges classes at runtime)\n fieldset: '',\n wrapper: 'relative w-full flex items-center rounded-rui-control bg-white dark:bg-transparent',\n input: [\n 'peer w-full bg-transparent px-3 py-1.5 text-sm/6 text-rui-text outline-hidden',\n 'placeholder:text-rui-neutral-500 dark:placeholder:text-rui-neutral-400',\n ].join(' '),\n inputWrapper: 'flex flex-1',\n // matching insets: a glyph sits 12px from either edge\n prepend: 'flex items-center gap-1 shrink-0 pl-3',\n append: 'flex items-center gap-1 shrink-0 pr-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 dense: {\n true: { input: 'py-1' },\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', input: 'text-rui-primary' },\n secondary: { prepend: 'text-rui-secondary', append: 'text-rui-secondary', input: 'text-rui-secondary' },\n error: { prepend: 'text-rui-error', append: 'text-rui-error', input: 'text-rui-error' },\n warning: { prepend: 'text-rui-warning', append: 'text-rui-warning', input: 'text-rui-warning' },\n info: { prepend: 'text-rui-info', append: 'text-rui-info', input: 'text-rui-info' },\n success: { prepend: 'text-rui-success', append: 'text-rui-success', input: '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});\n"],"mappings":";;;;;;;;;;;;AAYA,IAAa,kBAAkB,GAAG;CAChC,QAAQ;CACR,OAAO;EAEL,UAAU;EACV,SAAS;EACT,OAAO,CACL,iFACA,wEACF,CAAC,CAAC,KAAK,GAAG;EACV,cAAc;EAEd,SAAS;EACT,QAAQ;EACR,MAAM;EAEN,aAAa,CACX,mBACA,6FACF,CAAC,CAAC,KAAK,GAAG;CACZ;CACA,UAAU;EACR,OAAO,EACL,MAAM,EAAE,OAAO,OAAO,EACxB;EAEA,WAAW;GACT,SAAS;IAAE,SAAS;IAAoB,QAAQ;IAAoB,OAAO;GAAmB;GAC9F,WAAW;IAAE,SAAS;IAAsB,QAAQ;IAAsB,OAAO;GAAqB;GACtG,OAAO;IAAE,SAAS;IAAkB,QAAQ;IAAkB,OAAO;GAAiB;GACtF,SAAS;IAAE,SAAS;IAAoB,QAAQ;IAAoB,OAAO;GAAmB;GAC9F,MAAM;IAAE,SAAS;IAAiB,QAAQ;IAAiB,OAAO;GAAgB;GAClF,SAAS;IAAE,SAAS;IAAoB,QAAQ;IAAoB,OAAO;GAAmB;EAChG;EACA,UAAU,EACR,MAAM,EAAE,SAAS,4CAA4C,EAC/D;EAEA,UAAU,EACR,MAAM,EAAE,SAAS,iDAAiD,EACpE;CACF;AACF,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RuiFormTextDetail.js","names":["_sfc_main"],"sources":["../../../src/components/helpers/RuiFormTextDetail.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { useFormTextDetail } from '@/utils/form-text-detail';\n\nconst {\n errorMessages = [],\n successMessages = [],\n hint = '',\n} = defineProps<{\n errorMessages?: string | string[];\n successMessages?: string | string[];\n hint?: string;\n}>();\n\ndefineSlots<{\n /** Rich hint content, shown in place of the `hint` text while there is no error or success message. */\n hint?: () => any;\n}>();\n\nconst { formattedErrorMessages, formattedSuccessMessages, hasError, hasSuccess } =\n useFormTextDetail(\n () => errorMessages,\n () => successMessages,\n );\n
|
|
1
|
+
{"version":3,"file":"RuiFormTextDetail.js","names":["_sfc_main"],"sources":["../../../src/components/helpers/RuiFormTextDetail.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { type FormDetails, useFormTextDetail } from '@/utils/form-text-detail';\n\n/**\n * The line under a control. It is 20px: 4px of padding on the message above a 16px caption line,\n * so an `auto` line with nothing to show takes no space. The TransitionGroup has no `appear`: a\n * hint present on first render is in place when the field shows, and only a change of message\n * animates. The template keeps no comments, since a root-level one makes the component a fragment\n * in development and drops the class a parent passes.\n *\n * An error is clamped to two lines, since a backend error can run to several sentences and push a\n * dialog's footer down; the full text goes in `title` only while it is cut off. Screen readers get\n * all of it either way. Hints and success messages are not clamped: they are written for the field.\n */\nconst {\n errorMessages = [],\n successMessages = [],\n hint = '',\n details = 'reserve',\n} = defineProps<{\n errorMessages?: string | string[];\n successMessages?: string | string[];\n hint?: string;\n /** `reserve` keeps the line while empty; `auto` takes no space until there is a message. */\n details?: Exclude<FormDetails, 'hidden'>;\n}>();\n\ndefineSlots<{\n /** Rich hint content, shown in place of the `hint` text while there is no error or success message. */\n hint?: () => any;\n}>();\n\nconst { formattedErrorMessages, formattedSuccessMessages, hasError, hasSuccess } =\n useFormTextDetail(\n () => errorMessages,\n () => successMessages,\n );\n\nconst errorEl = useTemplateRef<HTMLDivElement>('error');\n\nconst errorClamped = ref<boolean>(false);\n\nconst errorMessage = computed<string | undefined>(() => get(formattedErrorMessages)[0]);\n\nfunction checkClamped(): void {\n const el = get(errorEl);\n set(errorClamped, !!el && el.scrollHeight > el.clientHeight + 1);\n}\n\nuseResizeObserver(errorEl, checkClamped);\n\nwatch(errorMessage, async () => {\n await nextTick();\n checkClamped();\n}, { flush: 'post' });\n</script>\n\n<template>\n <TransitionGroup\n tag=\"div\"\n class=\"details\"\n :class=\"{ 'min-h-5': details === 'reserve' }\"\n :data-details=\"details\"\n enter-from-class=\"opacity-0 -translate-y-2 h-0\"\n enter-active-class=\"transform transition\"\n enter-to-class=\"opacity-100 translate-y-0\"\n leave-from-class=\"opacity-100 -translate-y-2\"\n leave-active-class=\"transform transition\"\n leave-to-class=\"opacity-0 -translate-y-2 h-0\"\n >\n <div\n v-if=\"hasError\"\n key=\"error\"\n ref=\"error\"\n class=\"pt-1 text-xs/4 text-rui-error dark:text-rui-error-lighter line-clamp-2\"\n :title=\"errorClamped ? errorMessage : undefined\"\n data-id=\"details-error\"\n >\n {{ errorMessage }}\n </div>\n <div\n v-else-if=\"hasSuccess\"\n key=\"success\"\n class=\"pt-1 text-xs/4 text-rui-success\"\n >\n {{ formattedSuccessMessages[0] }}\n </div>\n <div\n v-else-if=\"$slots.hint || hint\"\n key=\"hint\"\n class=\"pt-1 text-xs/4 text-rui-text-secondary\"\n >\n <slot name=\"hint\">\n {{ hint }}\n </slot>\n </div>\n </TransitionGroup>\n</template>\n"],"mappings":""}
|
|
@@ -1,7 +1,21 @@
|
|
|
1
|
+
import { type FormDetails } from '../../utils/form-text-detail.js';
|
|
2
|
+
/**
|
|
3
|
+
* The line under a control. It is 20px: 4px of padding on the message above a 16px caption line,
|
|
4
|
+
* so an `auto` line with nothing to show takes no space. The TransitionGroup has no `appear`: a
|
|
5
|
+
* hint present on first render is in place when the field shows, and only a change of message
|
|
6
|
+
* animates. The template keeps no comments, since a root-level one makes the component a fragment
|
|
7
|
+
* in development and drops the class a parent passes.
|
|
8
|
+
*
|
|
9
|
+
* An error is clamped to two lines, since a backend error can run to several sentences and push a
|
|
10
|
+
* dialog's footer down; the full text goes in `title` only while it is cut off. Screen readers get
|
|
11
|
+
* all of it either way. Hints and success messages are not clamped: they are written for the field.
|
|
12
|
+
*/
|
|
1
13
|
type __VLS_Props = {
|
|
2
14
|
errorMessages?: string | string[];
|
|
3
15
|
successMessages?: string | string[];
|
|
4
16
|
hint?: string;
|
|
17
|
+
/** `reserve` keeps the line while empty; `auto` takes no space until there is a message. */
|
|
18
|
+
details?: Exclude<FormDetails, 'hidden'>;
|
|
5
19
|
};
|
|
6
20
|
type __VLS_Slots = {
|
|
7
21
|
/** Rich hint content, shown in place of the `hint` text while there is no error or success message. */
|