@poveste/controls 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +5 -0
  3. package/dist/components/HstCopyIcon.story.vue.d.ts +2 -0
  4. package/dist/components/HstCopyIcon.vue.d.ts +7 -0
  5. package/dist/components/HstWrapper.vue.d.ts +20 -0
  6. package/dist/components/button/HstButton.story.vue.d.ts +2 -0
  7. package/dist/components/button/HstButton.vue.d.ts +13 -0
  8. package/dist/components/button/HstButtonGroup.story.vue.d.ts +2 -0
  9. package/dist/components/button/HstButtonGroup.vue.d.ts +22 -0
  10. package/dist/components/checkbox/HstCheckbox.story.vue.d.ts +2 -0
  11. package/dist/components/checkbox/HstCheckbox.vue.d.ts +19 -0
  12. package/dist/components/checkbox/HstCheckboxList.story.vue.d.ts +2 -0
  13. package/dist/components/checkbox/HstCheckboxList.vue.d.ts +22 -0
  14. package/dist/components/checkbox/HstSimpleCheckbox.story.vue.d.ts +2 -0
  15. package/dist/components/checkbox/HstSimpleCheckbox.vue.d.ts +12 -0
  16. package/dist/components/colorselect/HstColorSelect.story.vue.d.ts +2 -0
  17. package/dist/components/colorselect/HstColorSelect.vue.d.ts +19 -0
  18. package/dist/components/design-tokens/HstColorShades.story.vue.d.ts +2 -0
  19. package/dist/components/design-tokens/HstColorShades.vue.d.ts +19 -0
  20. package/dist/components/design-tokens/HstTokenGrid.story.vue.d.ts +2 -0
  21. package/dist/components/design-tokens/HstTokenGrid.vue.d.ts +26 -0
  22. package/dist/components/design-tokens/HstTokenList.story.vue.d.ts +2 -0
  23. package/dist/components/design-tokens/HstTokenList.vue.d.ts +21 -0
  24. package/dist/components/json/HstJson.story.vue.d.ts +2 -0
  25. package/dist/components/json/HstJson.vue.d.ts +19 -0
  26. package/dist/components/number/HstNumber.story.vue.d.ts +2 -0
  27. package/dist/components/number/HstNumber.vue.d.ts +19 -0
  28. package/dist/components/radio/HstRadio.story.vue.d.ts +2 -0
  29. package/dist/components/radio/HstRadio.vue.d.ts +22 -0
  30. package/dist/components/select/CustomSelect.vue.d.ts +22 -0
  31. package/dist/components/select/HstSelect.story.vue.d.ts +2 -0
  32. package/dist/components/select/HstSelect.vue.d.ts +22 -0
  33. package/dist/components/slider/HstSlider.story.vue.d.ts +2 -0
  34. package/dist/components/slider/HstSlider.vue.d.ts +16 -0
  35. package/dist/components/text/HstText.story.vue.d.ts +2 -0
  36. package/dist/components/text/HstText.vue.d.ts +19 -0
  37. package/dist/components/textarea/HstTextarea.story.vue.d.ts +2 -0
  38. package/dist/components/textarea/HstTextarea.vue.d.ts +19 -0
  39. package/dist/index.d.ts +1047 -0
  40. package/dist/index.es.css +1 -0
  41. package/dist/index.es.js +16392 -0
  42. package/dist/style-standalone.css +973 -0
  43. package/dist/types.d.ts +4 -0
  44. package/dist/utils.d.ts +1 -0
  45. package/package.json +72 -0
  46. package/postcss.config.cjs +8 -0
  47. package/src/components/HstCopyIcon.story.vue +26 -0
  48. package/src/components/HstCopyIcon.vue +38 -0
  49. package/src/components/HstWrapper.vue +41 -0
  50. package/src/components/button/HstButton.story.vue +30 -0
  51. package/src/components/button/HstButton.vue +26 -0
  52. package/src/components/button/HstButtonGroup.story.vue +79 -0
  53. package/src/components/button/HstButtonGroup.vue +71 -0
  54. package/src/components/checkbox/HstCheckbox.spec.ts +28 -0
  55. package/src/components/checkbox/HstCheckbox.story.vue +47 -0
  56. package/src/components/checkbox/HstCheckbox.vue +56 -0
  57. package/src/components/checkbox/HstCheckboxList.story.vue +49 -0
  58. package/src/components/checkbox/HstCheckboxList.vue +82 -0
  59. package/src/components/checkbox/HstSimpleCheckbox.story.vue +28 -0
  60. package/src/components/checkbox/HstSimpleCheckbox.vue +82 -0
  61. package/src/components/checkbox/__snapshots__/HstCheckbox.spec.ts.snap +5 -0
  62. package/src/components/colorselect/HstColorSelect.story.vue +28 -0
  63. package/src/components/colorselect/HstColorSelect.vue +89 -0
  64. package/src/components/design-tokens/HstColorShades.story.vue +392 -0
  65. package/src/components/design-tokens/HstColorShades.vue +101 -0
  66. package/src/components/design-tokens/HstTokenGrid.story.vue +36 -0
  67. package/src/components/design-tokens/HstTokenGrid.vue +88 -0
  68. package/src/components/design-tokens/HstTokenList.story.vue +81 -0
  69. package/src/components/design-tokens/HstTokenList.vue +62 -0
  70. package/src/components/json/HstJson.story.vue +41 -0
  71. package/src/components/json/HstJson.vue +151 -0
  72. package/src/components/number/HstNumber.story.vue +42 -0
  73. package/src/components/number/HstNumber.vue +95 -0
  74. package/src/components/radio/HstRadio.story.vue +51 -0
  75. package/src/components/radio/HstRadio.vue +109 -0
  76. package/src/components/select/CustomSelect.vue +119 -0
  77. package/src/components/select/HstSelect.story.vue +161 -0
  78. package/src/components/select/HstSelect.vue +40 -0
  79. package/src/components/slider/HstSlider.story.vue +37 -0
  80. package/src/components/slider/HstSlider.vue +103 -0
  81. package/src/components/text/HstText.story.vue +63 -0
  82. package/src/components/text/HstText.vue +44 -0
  83. package/src/components/textarea/HstTextarea.story.vue +35 -0
  84. package/src/components/textarea/HstTextarea.vue +44 -0
  85. package/src/end.d.ts +8 -0
  86. package/src/index.ts +54 -0
  87. package/src/style/main.css +17 -0
  88. package/src/types.ts +4 -0
  89. package/src/utils.ts +12 -0
  90. package/tailwind.config.cjs +13 -0
  91. package/tsconfig.json +53 -0
  92. package/vite.config.ts +46 -0
@@ -0,0 +1,51 @@
1
+ <script lang="ts" setup>
2
+ import HstRadio from './HstRadio.vue'
3
+
4
+ const options = {
5
+ 'crash-bandicoot': 'Crash Bandicoot',
6
+ 'the-last-of-us': 'The Last of Us',
7
+ 'ghost-of-tsushima': 'Ghost of Tsushima',
8
+ }
9
+
10
+ const flatOptions = Object.keys(options)
11
+
12
+ const objectOptions = Object.keys(options).map(key => ({
13
+ label: options[key],
14
+ value: key,
15
+ }))
16
+
17
+ function initState() {
18
+ return {
19
+ character: flatOptions[0],
20
+ }
21
+ }
22
+ </script>
23
+
24
+ <template>
25
+ <Story
26
+ title="HstRadio"
27
+ group="controls"
28
+ :layout="{ type: 'single', iframe: false }"
29
+ >
30
+ <Variant
31
+ title="playground"
32
+ :init-state="initState"
33
+ >
34
+ <template #default="{ state }">
35
+ <HstRadio
36
+ v-model="state.character"
37
+ title="Label"
38
+ :options="objectOptions"
39
+ />
40
+ </template>
41
+
42
+ <template #controls="{ state }">
43
+ <HstRadio
44
+ v-model="state.character"
45
+ title="Label"
46
+ :options="objectOptions"
47
+ />
48
+ </template>
49
+ </Variant>
50
+ </Story>
51
+ </template>
@@ -0,0 +1,109 @@
1
+ <script lang="ts">
2
+ export default {
3
+ name: 'HstRadio',
4
+ }
5
+ </script>
6
+
7
+ <script lang="ts" setup>
8
+ import type { ComputedRef } from 'vue'
9
+ import type { HstControlOption } from '../../types'
10
+ import { computed, ref } from 'vue'
11
+ import HstWrapper from '../HstWrapper.vue'
12
+
13
+ const props = defineProps<{
14
+ title?: string
15
+ modelValue?: string | null
16
+ options: HstControlOption[]
17
+ }>()
18
+
19
+ const formattedOptions: ComputedRef<Record<string, string>> = computed(() => {
20
+ if (Array.isArray(props.options)) {
21
+ return Object.fromEntries(props.options.map((value: string | HstControlOption) => {
22
+ if (typeof value === 'string') {
23
+ return [value, value]
24
+ }
25
+ else {
26
+ return [value.value, value.label]
27
+ }
28
+ }))
29
+ }
30
+ return props.options
31
+ })
32
+
33
+ const emit = defineEmits<{
34
+ (e: 'update:modelValue', value: string): void
35
+ }>()
36
+
37
+ function selectOption(value: string) {
38
+ emit('update:modelValue', value)
39
+ animationEnabled.value = true
40
+ }
41
+
42
+ // animationEnabled prevents the animation from triggering on mounted
43
+ const animationEnabled = ref(false)
44
+ </script>
45
+
46
+ <template>
47
+ <HstWrapper
48
+ role="group"
49
+ :title="title"
50
+ class="histoire-radio htw-cursor-text"
51
+ :class="$attrs.class"
52
+ :style="$attrs.style"
53
+ >
54
+ <div class="-htw-my-1">
55
+ <template
56
+ v-for="(label, value) in formattedOptions"
57
+ :key="value"
58
+ >
59
+ <input
60
+ :id="`${value}-radio_${title}`"
61
+ type="radio"
62
+ :name="`${value}-radio_${title}`"
63
+ :value="value"
64
+ :checked="value === modelValue"
65
+ class="!htw-hidden"
66
+ @change="selectOption(value)"
67
+ >
68
+ <label
69
+ tabindex="0"
70
+ :for="`${value}-radio_${title}`"
71
+ class="htw-cursor-pointer htw-flex htw-items-center htw-relative htw-py-1 htw-group"
72
+ @keydown.enter.prevent="selectOption(value)"
73
+ @keydown.space.prevent="selectOption(value)"
74
+ >
75
+ <svg
76
+ width="16"
77
+ height="16"
78
+ viewBox="-12 -12 24 24"
79
+ class="htw-relative htw-z-10 htw-border htw-border-solid htw-text-inherit htw-rounded-full htw-box-border htw-inset-0 htw-transition-border htw-duration-150 htw-ease-out htw-mr-2 group-hover:htw-border-primary-500"
80
+ :class="[
81
+ modelValue === value
82
+ ? 'htw-border-primary-500'
83
+ : 'htw-border-black/25 dark:htw-border-white/25',
84
+ ]"
85
+ >
86
+ <circle
87
+ r="7"
88
+ class="htw-will-change-transform"
89
+ :class="[
90
+ animationEnabled ? 'htw-transition-all' : 'htw-transition-none',
91
+ {
92
+ 'htw-delay-150': modelValue === value,
93
+ },
94
+ modelValue === value
95
+ ? 'htw-fill-primary-500'
96
+ : 'htw-fill-transparent htw-scale-0',
97
+ ]"
98
+ />
99
+ </svg>
100
+ {{ label }}
101
+ </label>
102
+ </template>
103
+ </div>
104
+
105
+ <template #actions>
106
+ <slot name="actions" />
107
+ </template>
108
+ </HstWrapper>
109
+ </template>
@@ -0,0 +1,119 @@
1
+ <script lang="ts">
2
+ export default {
3
+ name: 'CustomSelect',
4
+ }
5
+ </script>
6
+
7
+ <script lang="ts" setup>
8
+ import type { ComputedRef } from 'vue'
9
+ import type { HstControlOption } from '../../types'
10
+ import { Icon } from '@iconify/vue'
11
+ import { Dropdown as VDropdown } from 'floating-vue'
12
+ import { computed } from 'vue'
13
+
14
+ const props = defineProps<{
15
+ modelValue: string
16
+ options: Record<string, any> | string[] | number[] | HstControlOption[]
17
+ }>()
18
+
19
+ const emit = defineEmits<{
20
+ (e: 'update:modelValue', value: string): void
21
+ }>()
22
+
23
+ const formattedOptions: ComputedRef<[any, string][]> = computed(() => {
24
+ if (Array.isArray(props.options)) {
25
+ return props.options.map((option) => {
26
+ if (typeof option === 'string' || typeof option === 'number') {
27
+ return [option, String(option)] as [any, string]
28
+ }
29
+ else {
30
+ return [option.value, option.label] as [any, string]
31
+ }
32
+ })
33
+ }
34
+ else {
35
+ return Object.entries(props.options)
36
+ }
37
+ })
38
+
39
+ const selectedLabel = computed(() => formattedOptions.value.find(([value]) => value === props.modelValue)?.[1])
40
+
41
+ function selectValue(value: any, hide: () => void) {
42
+ emit('update:modelValue', value)
43
+ hide()
44
+ }
45
+ </script>
46
+
47
+ <template>
48
+ <VDropdown
49
+ auto-size
50
+ auto-boundary-max-size
51
+ >
52
+ <div
53
+ class="htw-cursor-pointer htw-w-full htw-outline-none htw-px-2 htw-h-[27px] -htw-my-1 htw-border htw-border-solid htw-border-black/25 dark:htw-border-white/25 hover:htw-border-primary-500 dark:hover:htw-border-primary-500 htw-rounded-sm htw-flex htw-gap-2 htw-items-center htw-leading-normal"
54
+ >
55
+ <div class="htw-flex-1 htw-truncate">
56
+ <slot :label="selectedLabel">
57
+ {{ selectedLabel }}
58
+ </slot>
59
+ </div>
60
+ <Icon
61
+ icon="carbon:chevron-sort"
62
+ class="htw-w-4 htw-h-4 htw-flex-none htw-ml-auto"
63
+ />
64
+ </div>
65
+ <template #popper="{ hide }">
66
+ <div class="htw-flex htw-flex-col htw-bg-gray-50 dark:htw-bg-gray-700">
67
+ <div
68
+ v-for="[value, label] of formattedOptions"
69
+ v-bind="{ ...$attrs, class: null, style: null }"
70
+ :key="label"
71
+ class="htw-px-2 htw-py-1 htw-cursor-pointer hover:htw-bg-primary-100 dark:hover:htw-bg-primary-700"
72
+ :class="{
73
+ 'htw-bg-primary-200 dark:htw-bg-primary-800': props.modelValue === value,
74
+ }"
75
+ @click="selectValue(value, hide)"
76
+ >
77
+ {{ label }}
78
+ </div>
79
+ </div>
80
+ </template>
81
+ </VDropdown>
82
+ </template>
83
+
84
+ <style lang="postcss">
85
+ /* @TODO custom themes */
86
+
87
+ .v-popper {
88
+ line-height: 0;
89
+ }
90
+
91
+ .v-popper--theme-dropdown {
92
+ .htw-dark & {
93
+ .v-popper__inner {
94
+ @apply htw-bg-gray-700 htw-border-gray-850 htw-text-gray-100;
95
+ }
96
+
97
+ .v-popper__arrow-inner {
98
+ @apply htw-border-gray-700;
99
+ }
100
+
101
+ .v-popper__arrow-outer {
102
+ @apply htw-border-gray-850;
103
+ }
104
+ }
105
+
106
+ &.v-popper__popper--show-from .v-popper__wrapper {
107
+ transform: scale(.75);
108
+ }
109
+
110
+ &.v-popper__popper--show-to .v-popper__wrapper {
111
+ transform: none;
112
+ transition: transform .15s cubic-bezier(0, 1, .5, 1);
113
+ }
114
+ }
115
+
116
+ .v-popper__popper:focus-visible {
117
+ outline: none;
118
+ }
119
+ </style>
@@ -0,0 +1,161 @@
1
+ <script lang="ts" setup>
2
+ import HstSelect from './HstSelect.vue'
3
+
4
+ const options = {
5
+ 'crash-bandicoot': 'Crash Bandicoot',
6
+ 'the-last-of-us': 'The Last of Us',
7
+ 'ghost-of-tsushima': 'Ghost of Tsushima',
8
+ }
9
+
10
+ const flatOptions = Object.keys(options)
11
+
12
+ const objectOptions = Object.keys(options).map(key => ({
13
+ label: options[key],
14
+ value: key,
15
+ }))
16
+
17
+ const numberOptions = [0, 1, 2, 3, 4, 5]
18
+
19
+ function initState() {
20
+ return {
21
+ label: 'My really long label',
22
+ select: 'crash-bandicoot',
23
+ count: 0,
24
+ }
25
+ }
26
+ </script>
27
+
28
+ <template>
29
+ <Story
30
+ title="HstSelect"
31
+ group="controls"
32
+ :layout="{
33
+ type: 'grid',
34
+ width: '100%',
35
+ }"
36
+ >
37
+ <Variant
38
+ title="default"
39
+ :init-state="initState"
40
+ >
41
+ <template #default="{ state }">
42
+ <HstSelect
43
+ v-model="state.select"
44
+ :title="state.label"
45
+ :options="options"
46
+ />
47
+ </template>
48
+
49
+ <template #controls="{ state }">
50
+ <HstSelect
51
+ v-model="state.select"
52
+ title="Select"
53
+ :options="options"
54
+ />
55
+ </template>
56
+ </Variant>
57
+
58
+ <Variant
59
+ title="no-label"
60
+ :init-state="initState"
61
+ >
62
+ <template #default="{ state }">
63
+ <HstSelect
64
+ v-model="state.select"
65
+ :options="options"
66
+ />
67
+ </template>
68
+ <template #controls="{ state }">
69
+ <HstSelect
70
+ v-model="state.select"
71
+ title="Select"
72
+ :options="options"
73
+ />
74
+ </template>
75
+ </Variant>
76
+
77
+ <Variant
78
+ title="options-as-object"
79
+ :init-state="initState"
80
+ >
81
+ <template #default="{ state }">
82
+ <pre class="htw-text-xs htw-bg-gray-50 dark:htw-bg-gray-600 htw-rounded htw-p-4">{{ options }}</pre>
83
+ <HstSelect
84
+ v-model="state.select"
85
+ title="Games"
86
+ :options="options"
87
+ />
88
+ </template>
89
+ <template #controls="{ state }">
90
+ <HstSelect
91
+ v-model="state.select"
92
+ title="Games"
93
+ :options="options"
94
+ />
95
+ </template>
96
+ </Variant>
97
+
98
+ <Variant
99
+ title="options-as-array-of-objects"
100
+ :init-state="initState"
101
+ >
102
+ <template #default="{ state }">
103
+ <pre class="htw-text-xs htw-bg-gray-50 dark:htw-bg-gray-600 htw-rounded htw-p-4">{{ objectOptions }}</pre>
104
+ <HstSelect
105
+ v-model="state.select"
106
+ title="Games"
107
+ :options="objectOptions"
108
+ />
109
+ </template>
110
+ <template #controls="{ state }">
111
+ <HstSelect
112
+ v-model="state.select"
113
+ title="Games"
114
+ :options="objectOptions"
115
+ />
116
+ </template>
117
+ </Variant>
118
+
119
+ <Variant
120
+ title="options-as-array-of-strings"
121
+ :init-state="initState"
122
+ >
123
+ <template #default="{ state }">
124
+ <pre class="htw-text-xs htw-bg-gray-50 dark:htw-bg-gray-600 htw-rounded htw-p-4">{{ flatOptions }}</pre>
125
+ <HstSelect
126
+ v-model="state.select"
127
+ title="Select"
128
+ :options="flatOptions"
129
+ />
130
+ </template>
131
+ <template #controls="{ state }">
132
+ <HstSelect
133
+ v-model="state.select"
134
+ title="Select"
135
+ :options="flatOptions"
136
+ />
137
+ </template>
138
+ </Variant>
139
+
140
+ <Variant
141
+ title="options-as-array-of-numbers"
142
+ :init-state="initState"
143
+ >
144
+ <template #default="{ state }">
145
+ <pre class="htw-text-xs htw-bg-gray-50 dark:htw-bg-gray-600 htw-rounded htw-p-4">{{ numberOptions }}</pre>
146
+ <HstSelect
147
+ v-model="state.count"
148
+ title="Select"
149
+ :options="numberOptions"
150
+ />
151
+ </template>
152
+ <template #controls="{ state }">
153
+ <HstSelect
154
+ v-model="state.count"
155
+ title="Select"
156
+ :options="numberOptions"
157
+ />
158
+ </template>
159
+ </Variant>
160
+ </Story>
161
+ </template>
@@ -0,0 +1,40 @@
1
+ <script lang="ts">
2
+ export default {
3
+ name: 'HstSelect',
4
+ }
5
+ </script>
6
+
7
+ <script lang="ts" setup>
8
+ import type { HstControlOption } from '../../types'
9
+ import HstWrapper from '../HstWrapper.vue'
10
+ import CustomSelect from './CustomSelect.vue'
11
+
12
+ defineProps<{
13
+ title?: string
14
+ modelValue?: any
15
+ options: Record<string, any> | string[] | HstControlOption[]
16
+ }>()
17
+
18
+ const emit = defineEmits<{
19
+ (e: 'update:modelValue', value: any): void
20
+ }>()
21
+ </script>
22
+
23
+ <template>
24
+ <HstWrapper
25
+ :title="title"
26
+ class="histoire-select htw-cursor-text htw-items-center"
27
+ :class="$attrs.class"
28
+ :style="$attrs.style"
29
+ >
30
+ <CustomSelect
31
+ :options="options"
32
+ :model-value="modelValue"
33
+ @update:model-value="emit('update:modelValue', $event)"
34
+ />
35
+
36
+ <template #actions>
37
+ <slot name="actions" />
38
+ </template>
39
+ </HstWrapper>
40
+ </template>
@@ -0,0 +1,37 @@
1
+ <script lang="ts" setup>
2
+ import { reactive } from 'vue'
3
+ import HstSlider from './HstSlider.vue'
4
+
5
+ const state = reactive({
6
+ value: 20,
7
+ min: 0,
8
+ max: 100,
9
+ step: 5,
10
+ })
11
+ </script>
12
+
13
+ <template>
14
+ <Story
15
+ title="HstSlider"
16
+ group="controls"
17
+ :layout="{ type: 'single', iframe: false }"
18
+ >
19
+ <HstSlider
20
+ v-model="state.value"
21
+ :step="state.step"
22
+ :min="state.min"
23
+ :max="state.max"
24
+ title="Slide"
25
+ />
26
+ <pre>{{ state }}</pre>
27
+ <template #controls>
28
+ <HstSlider
29
+ v-model="state.value"
30
+ :step="state.step"
31
+ :min="state.min"
32
+ :max="state.max"
33
+ title="Value"
34
+ />
35
+ </template>
36
+ </Story>
37
+ </template>
@@ -0,0 +1,103 @@
1
+ <script lang="ts">
2
+ export default {
3
+ name: 'HstSlider',
4
+ inheritAttrs: false,
5
+ }
6
+ </script>
7
+
8
+ <script lang="ts" setup>
9
+ import type { CSSProperties } from 'vue'
10
+ import { VTooltip as vTooltip } from 'floating-vue'
11
+ import { computed, ref } from 'vue'
12
+ import HstWrapper from '../HstWrapper.vue'
13
+
14
+ const props = defineProps<{
15
+ title?: string
16
+ modelValue?: number | null
17
+ min: number
18
+ max: number
19
+ }>()
20
+
21
+ const emit = defineEmits({
22
+ 'update:modelValue': (newValue: number) => true,
23
+ })
24
+
25
+ const showTooltip = ref(false)
26
+ const input = ref<HTMLInputElement>(null)
27
+
28
+ const numberModel = computed({
29
+ get: () => props.modelValue,
30
+ set: (value) => {
31
+ emit('update:modelValue', value)
32
+ },
33
+ })
34
+
35
+ const percentage = computed(() => {
36
+ return (props.modelValue - props.min) / (props.max - props.min)
37
+ })
38
+
39
+ const tooltipStyle = computed<CSSProperties>(() => {
40
+ const gap = 8
41
+ if (input.value) {
42
+ const position = gap + ((input.value.clientWidth - 2 * gap) * percentage.value)
43
+ return {
44
+ left: `${position}px`,
45
+ }
46
+ }
47
+ return {}
48
+ })
49
+ </script>
50
+
51
+ <template>
52
+ <HstWrapper
53
+ class="histoire-slider htw-items-center"
54
+ :title="title"
55
+ :class="$attrs.class"
56
+ :style="$attrs.style"
57
+ >
58
+ <div class="htw-relative htw-w-full htw-flex htw-items-center">
59
+ <div class="htw-absolute htw-inset-0 htw-flex htw-items-center">
60
+ <div class="htw-border htw-border-black/25 dark:htw-border-white/25 htw-h-1 htw-w-full htw-rounded-full" />
61
+ </div>
62
+ <input
63
+ ref="input"
64
+ v-model.number="numberModel"
65
+ class="htw-range-input htw-appearance-none htw-border-0 htw-bg-transparent htw-cursor-pointer htw-relative htw-w-full htw-m-0 htw-text-gray-700"
66
+ type="range"
67
+ v-bind="{ ...$attrs, class: null, style: null, min, max }"
68
+ @mouseover="showTooltip = true"
69
+ @mouseleave="showTooltip = false"
70
+ >
71
+ <div
72
+ v-if="showTooltip"
73
+ v-tooltip="{ content: modelValue.toString(), shown: true, distance: 16, delay: 0 }"
74
+ class="htw-absolute"
75
+ :style="tooltipStyle"
76
+ />
77
+ </div>
78
+ </HstWrapper>
79
+ </template>
80
+
81
+ <style lang="pcss">
82
+ .htw-range-input {
83
+ &::-webkit-slider-thumb {
84
+ @apply htw-appearance-none htw-h-3 htw-w-3 htw-bg-white dark:htw-bg-gray-700 htw-border htw-border-solid htw-border-black/25 dark:htw-border-white/25 htw-rounded-full;
85
+ }
86
+
87
+ &:hover::-webkit-slider-thumb {
88
+ @apply !htw-bg-primary-500 !htw-border-primary-500;
89
+ }
90
+ }
91
+
92
+ /* Separate rules for -moz-range-thumb to prevent a bug with Safari that causes it to ignore custom style */
93
+
94
+ .htw-range-input {
95
+ &::-moz-range-thumb {
96
+ @apply htw-appearance-none htw-h-3 htw-w-3 htw-bg-white dark:htw-bg-gray-700 htw-border htw-border-solid htw-border-black/25 dark:htw-border-white/25 htw-rounded-full;
97
+ }
98
+
99
+ &:hover::-moz-range-thumb {
100
+ @apply !htw-bg-primary-500 !htw-border-primary-500;
101
+ }
102
+ }
103
+ </style>
@@ -0,0 +1,63 @@
1
+ <script lang="ts" setup>
2
+ import HstText from './HstText.vue'
3
+
4
+ function initState() {
5
+ return {
6
+ label: 'My really long label',
7
+ text: '',
8
+ }
9
+ }
10
+ </script>
11
+
12
+ <template>
13
+ <Story
14
+ title="HstText"
15
+ group="controls"
16
+ :layout="{
17
+ type: 'grid',
18
+ width: '100%',
19
+ }"
20
+ >
21
+ <Variant
22
+ title="default"
23
+ :init-state="initState"
24
+ >
25
+ <template #default="{ state }">
26
+ <HstText
27
+ v-model="state.text"
28
+ :title="state.label"
29
+ />
30
+ </template>
31
+
32
+ <template #controls="{ state }">
33
+ <HstText
34
+ v-model="state.label"
35
+ title="Label"
36
+ />
37
+ <HstText
38
+ v-model="state.text"
39
+ title="Text"
40
+ />
41
+ </template>
42
+ </Variant>
43
+
44
+ <Variant
45
+ title="no-label"
46
+ :init-state="initState"
47
+ >
48
+ <template #default="{ state }">
49
+ <HstText
50
+ v-model="state.text"
51
+ placeholder="Enter some text..."
52
+ />
53
+ </template>
54
+
55
+ <template #controls="{ state }">
56
+ <HstText
57
+ v-model="state.text"
58
+ title="Text"
59
+ />
60
+ </template>
61
+ </Variant>
62
+ </Story>
63
+ </template>