opui-css 5.2.0 → 5.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/components/Accordion/Accordion.vue +38 -0
  3. package/components/Anchor/Anchor.vue +41 -0
  4. package/components/Avatar/Avatar.vue +24 -0
  5. package/components/Avatar/types.d.vue.ts +2 -2
  6. package/components/Badge/Badge.vue +39 -0
  7. package/components/Button/Button.vue +27 -0
  8. package/components/Button/types.ts +0 -3
  9. package/components/ButtonGroup/ButtonGroup.vue +22 -0
  10. package/components/Callout/Callout.vue +63 -0
  11. package/components/Card/Card.vue +28 -0
  12. package/components/Card/types.ts +1 -0
  13. package/components/Checkbox/Checkbox.vue +43 -0
  14. package/components/Checkbox/CheckboxInput.vue +32 -0
  15. package/components/Checkbox/types.ts +0 -1
  16. package/components/Chip/Chip.vue +37 -0
  17. package/components/ClassicSelect/ClassicSelect.vue +54 -0
  18. package/components/ClassicSelect/types.ts +0 -4
  19. package/components/DescriptionList/Description.vue +12 -0
  20. package/components/DescriptionList/DescriptionList.vue +23 -0
  21. package/components/DescriptionList/Item.vue +12 -0
  22. package/components/DescriptionList/Term.vue +12 -0
  23. package/components/Dialog/Dialog.vue +35 -0
  24. package/components/Dialog/types.ts +1 -0
  25. package/components/Divider/Divider.vue +12 -0
  26. package/components/Drawer/Drawer.astro +9 -3
  27. package/components/Drawer/Drawer.vue +46 -0
  28. package/components/Drawer/DrawerFooter.vue +16 -0
  29. package/components/Drawer/DrawerHeader.vue +36 -0
  30. package/components/Drawer/types.d.vue.ts +3 -1
  31. package/components/Drawer/types.ts +1 -0
  32. package/components/FieldDescription/FieldDescription.vue +12 -0
  33. package/components/FieldGroup/FieldGroup.vue +25 -0
  34. package/components/FieldLegend/FieldLegend.vue +18 -0
  35. package/components/FieldSet/FieldSet.vue +18 -0
  36. package/components/Form/Form.vue +14 -0
  37. package/components/IconButton/IconButton.vue +24 -0
  38. package/components/List/List.vue +28 -0
  39. package/components/ListItem/ListItem.vue +98 -0
  40. package/components/Progress/Progress.vue +34 -0
  41. package/components/Radio/Radio.vue +41 -0
  42. package/components/Radio/RadioInput.vue +14 -0
  43. package/components/Radio/types.ts +0 -1
  44. package/components/Range/Range.vue +85 -0
  45. package/components/Range/types.ts +0 -5
  46. package/components/Select/Select.astro +0 -6
  47. package/components/Select/Select.vue +85 -0
  48. package/components/Switch/Switch.vue +63 -0
  49. package/components/Switch/SwitchInput.vue +14 -0
  50. package/components/Table/Body.vue +5 -0
  51. package/components/Table/Cell.vue +5 -0
  52. package/components/Table/Column.vue +19 -0
  53. package/components/Table/ColumnGroup.vue +5 -0
  54. package/components/Table/Head.vue +5 -0
  55. package/components/Table/HeaderCell.vue +5 -0
  56. package/components/Table/Row.vue +5 -0
  57. package/components/Table/Table.vue +19 -0
  58. package/components/Tabs/Tabs.vue +20 -0
  59. package/components/Tabs/TabsItem.vue +39 -0
  60. package/components/Tabs/TabsPanel.vue +31 -0
  61. package/components/Tabs/TabsTab.vue +24 -0
  62. package/components/TextField/TextField.vue +74 -0
  63. package/components/TextField/types.d.vue.ts +3 -1
  64. package/components/Textarea/Textarea.vue +64 -0
  65. package/components/Textarea/types.d.vue.ts +1 -0
  66. package/components/Toast/Toast.vue +48 -0
  67. package/components/ToggleButton/ToggleButton.vue +41 -0
  68. package/components/ToggleGroup/ToggleGroup.vue +36 -0
  69. package/components/Tooltip/Tooltip.vue +22 -0
  70. package/core/normalize.css +24 -10
  71. package/core/utils.css +1 -3
  72. package/css/components/accordion.css +4 -5
  73. package/css/components/button.css +5 -4
  74. package/css/components/dialog.css +8 -13
  75. package/css/components/drawer.css +2 -1
  76. package/css/components/icon-button.css +8 -10
  77. package/css/components/progress.css +23 -27
  78. package/css/components/range.css +3 -6
  79. package/css/components/select.css +6 -7
  80. package/css/components/switch.css +17 -18
  81. package/css/components/text-field.css +3 -3
  82. package/dist/opui.components.css +79 -94
  83. package/dist/opui.components.css.map +1 -1
  84. package/dist/opui.css +104 -107
  85. package/dist/opui.css.map +1 -1
  86. package/package.json +14 -3
  87. package/vue/index.ts +54 -0
@@ -0,0 +1,46 @@
1
+ <script setup lang="ts">
2
+ import { useId } from "vue"
3
+ import type { DrawerSlots, Props } from "./types.d.vue"
4
+
5
+ const {
6
+ backdrop = "blurred",
7
+ closedby = "any",
8
+ id,
9
+ scrollLock = true,
10
+ side = "inline-start",
11
+ } = defineProps<Props>()
12
+ const slots = defineSlots<DrawerSlots>()
13
+
14
+ defineOptions({
15
+ inheritAttrs: false,
16
+ })
17
+
18
+ const drawerId = id || useId()
19
+ </script>
20
+
21
+ <template>
22
+ <dialog
23
+ :id="drawerId"
24
+ :class="[
25
+ 'ui-drawer',
26
+ side && `ui-${side}`,
27
+ {
28
+ 'ui-backdrop-transparent': backdrop === 'transparent',
29
+ 'ui-scroll-lock': scrollLock,
30
+ },
31
+ $props.class,
32
+ ]"
33
+ :closedby="closedby"
34
+ v-bind="$attrs"
35
+ >
36
+ <slot v-if="slots.header" name="header"></slot>
37
+
38
+ <div v-if="slots.content" class="ui-content">
39
+ <slot name="content"></slot>
40
+ </div>
41
+
42
+ <slot></slot>
43
+
44
+ <slot v-if="slots.footer" name="footer"></slot>
45
+ </dialog>
46
+ </template>
@@ -0,0 +1,16 @@
1
+ <script setup lang="ts">
2
+ import type { DrawerFooterProps, DrawerFooterSlots } from "./types.d.vue"
3
+
4
+ defineProps<DrawerFooterProps>()
5
+ defineSlots<DrawerFooterSlots>()
6
+
7
+ defineOptions({
8
+ inheritAttrs: false,
9
+ })
10
+ </script>
11
+
12
+ <template>
13
+ <div :class="['ui-footer', $props.class]" v-bind="$attrs">
14
+ <slot></slot>
15
+ </div>
16
+ </template>
@@ -0,0 +1,36 @@
1
+ <script setup lang="ts">
2
+ import IconButton from "../IconButton/IconButton.vue"
3
+ import type { DrawerHeaderProps, DrawerHeaderSlots } from "./types.d.vue"
4
+
5
+ const { heading } = defineProps<DrawerHeaderProps>()
6
+ defineSlots<DrawerHeaderSlots>()
7
+
8
+ defineOptions({
9
+ inheritAttrs: false,
10
+ })
11
+
12
+ const closeDrawer = (event: MouseEvent) => {
13
+ const target = event.currentTarget as HTMLElement | null
14
+ target?.closest("dialog")?.close()
15
+ }
16
+ </script>
17
+
18
+ <template>
19
+ <div :class="['ui-header', $props.class]" v-bind="$attrs">
20
+ <span v-if="heading">{{ heading }}</span>
21
+ <slot></slot>
22
+ <IconButton title="Close" @click="closeDrawer">
23
+ <svg
24
+ xmlns="http://www.w3.org/2000/svg"
25
+ width="32"
26
+ height="32"
27
+ viewBox="0 0 32 32"
28
+ >
29
+ <path
30
+ fill="currentColor"
31
+ d="M26.29 4.293a1 1 0 1 1 1.414 1.414L17.413 16l10.291 10.29a1 1 0 1 1-1.414 1.414L16 17.413L5.707 27.704a1 1 0 0 1-1.414-1.414L14.585 16L4.293 5.707a1 1 0 0 1 1.414-1.414L16 14.584z"
32
+ ></path>
33
+ </svg>
34
+ </IconButton>
35
+ </div>
36
+ </template>
@@ -18,7 +18,9 @@ export type DrawerFooterProps = BaseDrawerFooterProps & {
18
18
  class?: HTMLAttributes["class"]
19
19
  }
20
20
 
21
- export type DrawerSlots = BaseSlots<Slot>
21
+ export type DrawerSlots = BaseSlots<Slot> & {
22
+ default?: Slot
23
+ }
22
24
 
23
25
  export type DrawerHeaderSlots = {
24
26
  default?: Slot
@@ -13,6 +13,7 @@ export type DrawerHeaderProps = {
13
13
  export type DrawerFooterProps = {}
14
14
 
15
15
  export type Slots<S> = {
16
+ children?: S
16
17
  content?: S
17
18
  footer?: S
18
19
  header?: S
@@ -0,0 +1,12 @@
1
+ <script setup lang="ts">
2
+ import type { Props, Slots } from "./types.d.vue"
3
+
4
+ const props = defineProps<Props>()
5
+ defineSlots<Slots>()
6
+ </script>
7
+
8
+ <template>
9
+ <p :class="['ui-field-description', props.class]" v-bind="$attrs">
10
+ <slot></slot>
11
+ </p>
12
+ </template>
@@ -0,0 +1,25 @@
1
+ <script setup lang="ts">
2
+ import { provide } from "vue"
3
+ import { CurrentFieldNameKey, type Props, type Slots } from "./types.d.vue"
4
+
5
+ const props = defineProps<Props>()
6
+ defineSlots<Slots>()
7
+
8
+ if (props.name) {
9
+ provide(CurrentFieldNameKey, props.name)
10
+ }
11
+ </script>
12
+
13
+ <template>
14
+ <div
15
+ :class="[
16
+ 'ui-field-group',
17
+ props.direction && `ui-${props.direction}`,
18
+ props.class,
19
+ ]"
20
+ v-bind="$attrs"
21
+ role="group"
22
+ >
23
+ <slot></slot>
24
+ </div>
25
+ </template>
@@ -0,0 +1,18 @@
1
+ <script setup lang="ts">
2
+ import type { Props, Slots } from "./types.d.vue"
3
+
4
+ const props = withDefaults(defineProps<Props>(), {
5
+ as: "legend",
6
+ })
7
+ defineSlots<Slots>()
8
+ </script>
9
+
10
+ <template>
11
+ <component
12
+ :is="props.as"
13
+ :class="[{ 'ui-legend': props.as !== 'legend' }, props.class]"
14
+ v-bind="$attrs"
15
+ >
16
+ <slot></slot>
17
+ </component>
18
+ </template>
@@ -0,0 +1,18 @@
1
+ <script setup lang="ts">
2
+ import type { Props, Slots } from "./types.d.vue"
3
+
4
+ const props = withDefaults(defineProps<Props>(), {
5
+ as: "fieldset",
6
+ })
7
+ defineSlots<Slots>()
8
+ </script>
9
+
10
+ <template>
11
+ <component
12
+ :is="props.as"
13
+ :class="['ui-fieldset', props.class]"
14
+ v-bind="$attrs"
15
+ >
16
+ <slot></slot>
17
+ </component>
18
+ </template>
@@ -0,0 +1,14 @@
1
+ <script setup lang="ts">
2
+ import type { Props, Slots } from "./types.d.vue"
3
+
4
+ const props = withDefaults(defineProps<Props>(), {
5
+ as: "form",
6
+ })
7
+ defineSlots<Slots>()
8
+ </script>
9
+
10
+ <template>
11
+ <component :is="props.as" :class="['ui-form', props.class]" v-bind="$attrs">
12
+ <slot></slot>
13
+ </component>
14
+ </template>
@@ -0,0 +1,24 @@
1
+ <script setup lang="ts">
2
+ import type { Props, Slots } from "./types.d.vue"
3
+
4
+ const { as, color, href, size, variant } = defineProps<Props>()
5
+ defineSlots<Slots>()
6
+
7
+ const Tag = as || (href ? "a" : "button")
8
+ </script>
9
+
10
+ <template>
11
+ <component
12
+ :is="Tag"
13
+ :class="[
14
+ 'ui-icon-button',
15
+ size && `ui-${size}`,
16
+ variant && `ui-${variant}`,
17
+ color && `ui-${color}`,
18
+ $props.class,
19
+ ]"
20
+ :href="href"
21
+ >
22
+ <slot></slot>
23
+ </component>
24
+ </template>
@@ -0,0 +1,28 @@
1
+ <script setup lang="ts">
2
+ import type { Props, Slots } from "./types.d.vue"
3
+
4
+ const { bordered, dense, gutterless, variant } = defineProps<Props>()
5
+ defineSlots<Slots>()
6
+
7
+ defineOptions({
8
+ inheritAttrs: false,
9
+ })
10
+ </script>
11
+
12
+ <template>
13
+ <ul
14
+ :class="[
15
+ 'ui-list',
16
+ {
17
+ 'ui-bordered': bordered,
18
+ 'ui-dense': dense,
19
+ 'ui-gutterless': gutterless,
20
+ },
21
+ variant && `ui-${variant}`,
22
+ $props.class,
23
+ ]"
24
+ v-bind="$attrs"
25
+ >
26
+ <slot></slot>
27
+ </ul>
28
+ </template>
@@ -0,0 +1,98 @@
1
+ <script setup lang="ts">
2
+ import { computed, useAttrs } from "vue"
3
+ import type { Props, Slots } from "./types.d.vue"
4
+
5
+ const props = defineProps<Props>()
6
+ const slots = defineSlots<Slots>()
7
+ const attrs = useAttrs()
8
+
9
+ defineOptions({
10
+ inheritAttrs: false,
11
+ })
12
+
13
+ const hasLabel = computed(
14
+ () =>
15
+ props.type &&
16
+ (props.type === "checkbox" ||
17
+ props.type === "radio" ||
18
+ props.type === "switch"),
19
+ )
20
+ const labelClass = computed(() => props.type || "")
21
+ const Tag = computed(() => props.as)
22
+
23
+ const liAttrs = computed(() => (Tag.value ? {} : attrs))
24
+ const innerAttrs = computed(() => (Tag.value ? attrs : {}))
25
+ </script>
26
+
27
+ <template>
28
+ <li
29
+ :class="[
30
+ {
31
+ 'ui-border-top': props.borderTop,
32
+ 'ui-inset': props.inset,
33
+ },
34
+ props.class,
35
+ ]"
36
+ v-bind="liAttrs"
37
+ >
38
+ <label
39
+ v-if="hasLabel"
40
+ :class="labelClass && `ui-${labelClass}`"
41
+ :for="props.for"
42
+ >
43
+ <div v-if="slots.start" class="ui-start">
44
+ <slot name="start"></slot>
45
+ </div>
46
+ <div
47
+ v-if="slots.text || props.headline || props.description"
48
+ class="ui-text"
49
+ >
50
+ <p v-if="props.headline">{{ props.headline }}</p>
51
+ <p v-if="props.description">{{ props.description }}</p>
52
+ <slot name="text"></slot>
53
+ </div>
54
+ <div v-if="slots.end" class="ui-end">
55
+ <slot name="end"></slot>
56
+ </div>
57
+ <slot></slot>
58
+ </label>
59
+
60
+ <component :is="Tag" v-else-if="Tag" v-bind="innerAttrs">
61
+ <div v-if="slots.start" class="ui-start">
62
+ <slot name="start"></slot>
63
+ </div>
64
+ <div
65
+ v-if="props.headline || props.description || slots.text"
66
+ class="ui-text"
67
+ >
68
+ <p v-if="props.headline">{{ props.headline }}</p>
69
+ <p v-if="props.description">{{ props.description }}</p>
70
+ <slot name="text"></slot>
71
+ <slot></slot>
72
+ </div>
73
+ <slot v-else></slot>
74
+ <div v-if="slots.end" class="ui-end">
75
+ <slot name="end"></slot>
76
+ </div>
77
+ </component>
78
+
79
+ <template v-else>
80
+ <div v-if="slots.start" class="ui-start">
81
+ <slot name="start"></slot>
82
+ </div>
83
+ <div
84
+ v-if="props.headline || props.description || slots.text"
85
+ class="ui-text"
86
+ >
87
+ <p v-if="props.headline">{{ props.headline }}</p>
88
+ <p v-if="props.description">{{ props.description }}</p>
89
+ <slot name="text"></slot>
90
+ <slot></slot>
91
+ </div>
92
+ <slot v-else></slot>
93
+ <div v-if="slots.end" class="ui-end">
94
+ <slot name="end"></slot>
95
+ </div>
96
+ </template>
97
+ </li>
98
+ </template>
@@ -0,0 +1,34 @@
1
+ <script setup lang="ts">
2
+ import type { Props, Slots } from "./types.d.vue"
3
+
4
+ defineOptions({
5
+ inheritAttrs: false,
6
+ })
7
+
8
+ defineSlots<Slots>()
9
+ const {
10
+ "aria-busy": ariaBusy,
11
+ "aria-describedby": ariaDescribedby,
12
+ "aria-label": ariaLabel,
13
+ id,
14
+ max,
15
+ value,
16
+ variant,
17
+ } = defineProps<Props>()
18
+ </script>
19
+
20
+ <template>
21
+ <div :class="['ui-progress', variant && `ui-${variant}`, $props.class]">
22
+ <progress
23
+ v-bind="$attrs"
24
+ :aria-busy="ariaBusy"
25
+ :aria-describedby="ariaDescribedby"
26
+ :aria-label="ariaLabel"
27
+ :id="id"
28
+ :max="max"
29
+ :value="value"
30
+ >
31
+ <slot></slot>
32
+ </progress>
33
+ </div>
34
+ </template>
@@ -0,0 +1,41 @@
1
+ <script setup lang="ts">
2
+ import RadioInput from "./RadioInput.vue"
3
+ import type { RadioProps, Slots } from "./types.d.vue"
4
+ import { useId } from "vue"
5
+
6
+ defineOptions({
7
+ inheritAttrs: false,
8
+ })
9
+
10
+ const props = defineProps<RadioProps>()
11
+ defineSlots<Slots>()
12
+ const modelValue = defineModel<string | number | boolean>()
13
+
14
+ const endTextId = useId()
15
+ </script>
16
+
17
+ <template>
18
+ <label
19
+ :class="[
20
+ 'ui-radio',
21
+ props.size && `ui-${props.size}`,
22
+ {
23
+ 'ui-stack': props.stack,
24
+ },
25
+ props.class,
26
+ ]"
27
+ :data-invalid="props.error || undefined"
28
+ >
29
+ <RadioInput
30
+ v-bind="$attrs"
31
+ v-model="modelValue"
32
+ :aria-describedby="endTextId"
33
+ />
34
+ <span :class="[props.hideLabel ? 'ui-sr-only' : 'ui-label']"
35
+ ><slot></slot
36
+ ></span>
37
+ <span :id="endTextId" class="ui-end-text" v-if="$slots['end-text']">
38
+ <slot name="end-text"></slot>
39
+ </span>
40
+ </label>
41
+ </template>
@@ -0,0 +1,14 @@
1
+ <script setup lang="ts">
2
+ import type { RadioInputProps } from "./types"
3
+
4
+ defineOptions({
5
+ inheritAttrs: false,
6
+ })
7
+
8
+ defineProps<RadioInputProps>()
9
+ const modelValue = defineModel<string | number | boolean>()
10
+ </script>
11
+
12
+ <template>
13
+ <input type="radio" v-bind="$attrs" v-model="modelValue" />
14
+ </template>
@@ -1,5 +1,4 @@
1
1
  export type RadioProps = {
2
- disabled?: boolean
3
2
  error?: boolean
4
3
  hideLabel?: boolean
5
4
  size?: "small" | "large"
@@ -0,0 +1,85 @@
1
+ <script setup lang="ts">
2
+ import type { RangeProps, Slots } from "./types.d.vue"
3
+ import { useId } from "vue"
4
+
5
+ defineOptions({
6
+ inheritAttrs: false,
7
+ })
8
+
9
+ const props = defineProps<RangeProps>()
10
+ defineSlots<Slots>()
11
+ const modelValue = defineModel<number | string>()
12
+
13
+ const inputId = props.id || useId()
14
+ const labelId = useId()
15
+ const startTextId = useId()
16
+ const endTextId = useId()
17
+ </script>
18
+
19
+ <template>
20
+ <label
21
+ :class="[
22
+ 'ui-range',
23
+ props.variant && `ui-${props.variant}`,
24
+ { 'ui-spread': props.spread },
25
+ props.class,
26
+ ]"
27
+ >
28
+ <span v-if="props.label || $slots.default" class="ui-label" :id="labelId">
29
+ <slot>{{ props.label }}</slot>
30
+ </span>
31
+ <output
32
+ v-if="props.valueSuffix !== undefined || $slots.value"
33
+ class="ui-value"
34
+ :for="inputId"
35
+ :data-suffix="props.valueSuffix"
36
+ >
37
+ <slot name="value">{{ modelValue ?? props.value }}</slot>
38
+ </output>
39
+ <span
40
+ v-if="props.startText || $slots['start-text']"
41
+ class="ui-start-text"
42
+ :id="startTextId"
43
+ >
44
+ <slot name="start-text">{{ props.startText }}</slot>
45
+ </span>
46
+
47
+ <input
48
+ :aria-describedby="
49
+ [
50
+ props.startText || $slots['start-text'] ? startTextId : undefined,
51
+ props.endText || $slots['end-text'] ? endTextId : undefined,
52
+ ]
53
+ .filter(Boolean)
54
+ .join(' ') || undefined
55
+ "
56
+ :aria-labelledby="labelId"
57
+ :id="inputId"
58
+ :list="props.list"
59
+ type="range"
60
+ v-bind="$attrs"
61
+ v-model="modelValue"
62
+ />
63
+
64
+ <datalist v-if="props.options || $slots.datalist" :id="props.list">
65
+ <template
66
+ v-for="option in props.options"
67
+ :key="typeof option === 'object' ? option.value : option"
68
+ >
69
+ <option
70
+ :value="typeof option === 'object' ? option.value : option"
71
+ :label="typeof option === 'object' ? option.label : undefined"
72
+ />
73
+ </template>
74
+ <slot name="datalist"></slot>
75
+ </datalist>
76
+
77
+ <span
78
+ v-if="props.endText || $slots['end-text']"
79
+ class="ui-end-text"
80
+ :id="endTextId"
81
+ >
82
+ <slot name="end-text">{{ props.endText }}</slot>
83
+ </span>
84
+ </label>
85
+ </template>
@@ -1,15 +1,10 @@
1
1
  export type RangeProps = {
2
2
  [key: string]: any
3
- disabled?: boolean
4
3
  endText?: string
5
4
  id?: string
6
5
  label?: string
7
- max?: number | string
8
- min?: number | string
9
- name?: string
10
6
  spread?: boolean
11
7
  startText?: string
12
- step?: number | string
13
8
  value?: number | string
14
9
  valueSuffix?: string
15
10
  variant?: "filled" | "default" | "tonal"
@@ -6,7 +6,6 @@ export const title = "Select"
6
6
  const {
7
7
  class: className,
8
8
  description,
9
- disabled,
10
9
  error,
11
10
  dense,
12
11
  id,
@@ -16,8 +15,6 @@ const {
16
15
  spread,
17
16
  size,
18
17
  endText,
19
- required,
20
- value,
21
18
  variant = "outlined",
22
19
  ...rest
23
20
  } = Astro.props
@@ -59,11 +56,8 @@ const labelId = $id("select-label")
59
56
  <span class="ui-field">
60
57
  <select
61
58
  aria-labelledby={label ? labelId : undefined}
62
- disabled={disabled}
63
59
  id={selectId}
64
60
  name={fieldName}
65
- required={required}
66
- value={value}
67
61
  {...rest}
68
62
  >
69
63
  <button>
@@ -0,0 +1,85 @@
1
+ <script setup lang="ts">
2
+ import { useId } from "vue"
3
+ import type { Props, Slots } from "./types.d.vue"
4
+
5
+ defineOptions({
6
+ inheritAttrs: false,
7
+ })
8
+
9
+ const props = withDefaults(defineProps<Props>(), {
10
+ items: () => [],
11
+ variant: "outlined",
12
+ })
13
+ defineSlots<Slots>()
14
+ const modelValue = defineModel<string | number | (string | number)[]>()
15
+
16
+ const selectId = props.id || useId()
17
+ const labelId = useId()
18
+ const endTextId = useId()
19
+ </script>
20
+
21
+ <template>
22
+ <label
23
+ :class="[
24
+ 'ui-select',
25
+ props.size && `ui-${props.size}`,
26
+ {
27
+ 'ui-filled': props.variant === 'filled',
28
+ 'ui-spread': props.spread,
29
+ },
30
+ props.class,
31
+ ]"
32
+ :data-invalid="props.error || undefined"
33
+ >
34
+ <span v-if="props.label || $slots.label" class="ui-label" :id="labelId">
35
+ <slot name="label">{{ props.label }}</slot>
36
+ </span>
37
+
38
+ <span v-if="props.description || $slots.description" class="ui-start-text">
39
+ <slot name="description">{{ props.description }}</slot>
40
+ </span>
41
+
42
+ <span class="ui-field">
43
+ <select
44
+ :aria-labelledby="props.label ? labelId : undefined"
45
+ :id="selectId"
46
+ v-bind="$attrs"
47
+ v-model="modelValue"
48
+ >
49
+ <button v-pre>
50
+ <selectedcontent></selectedcontent>
51
+ </button>
52
+ <div :class="['ui-list', { 'ui-dense': props.dense }]">
53
+ <option
54
+ v-for="item in props.items"
55
+ :key="item.value"
56
+ :value="item.value"
57
+ >
58
+ {{ item.text }}
59
+ </option>
60
+ <slot></slot>
61
+ </div>
62
+ </select>
63
+ <span class="ui-prefix" v-if="$slots.prefix"
64
+ ><slot name="prefix"></slot
65
+ ></span>
66
+ <span class="ui-suffix" v-if="$slots.suffix"
67
+ ><slot name="suffix"></slot
68
+ ></span>
69
+ <span class="ui-header" v-if="$slots.header"
70
+ ><slot name="header"></slot
71
+ ></span>
72
+ <span class="ui-footer" v-if="$slots.footer"
73
+ ><slot name="footer"></slot
74
+ ></span>
75
+ </span>
76
+
77
+ <span
78
+ v-if="props.endText || $slots['end-text']"
79
+ :id="endTextId"
80
+ class="ui-end-text"
81
+ >
82
+ <slot name="end-text">{{ props.endText }}</slot>
83
+ </span>
84
+ </label>
85
+ </template>