windly-ui 1.0.1 → 1.0.2

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 (39) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +57 -33
  3. package/package.json +47 -15
  4. package/ui-library/dist/module.d.mts +3 -0
  5. package/ui-library/dist/module.json +8 -0
  6. package/ui-library/dist/module.mjs +22 -0
  7. package/ui-library/dist/types.d.mts +7 -0
  8. package/ui-library/components/Accordion.vue +0 -118
  9. package/ui-library/components/Avatar.vue +0 -121
  10. package/ui-library/components/Badge.vue +0 -116
  11. package/ui-library/components/Breadcrumbs.vue +0 -138
  12. package/ui-library/components/Button.vue +0 -154
  13. package/ui-library/components/Card.vue +0 -84
  14. package/ui-library/components/Checkbox.vue +0 -148
  15. package/ui-library/components/CodeBlock.vue +0 -99
  16. package/ui-library/components/ColorPicker.vue +0 -302
  17. package/ui-library/components/Date.vue +0 -240
  18. package/ui-library/components/Dialog.vue +0 -187
  19. package/ui-library/components/Divider.vue +0 -78
  20. package/ui-library/components/Drawer.vue +0 -67
  21. package/ui-library/components/Dropdown.vue +0 -248
  22. package/ui-library/components/FileUploader.vue +0 -330
  23. package/ui-library/components/Icon.vue +0 -82
  24. package/ui-library/components/Image.vue +0 -78
  25. package/ui-library/components/Input.vue +0 -531
  26. package/ui-library/components/Radio.vue +0 -356
  27. package/ui-library/components/ScrollArea.vue +0 -43
  28. package/ui-library/components/Select.vue +0 -309
  29. package/ui-library/components/Stepper.vue +0 -361
  30. package/ui-library/components/TabPanel.vue +0 -25
  31. package/ui-library/components/Table.vue +0 -152
  32. package/ui-library/components/Tabs.vue +0 -71
  33. package/ui-library/components/Textarea.vue +0 -233
  34. package/ui-library/components/Toggle.vue +0 -319
  35. package/ui-library/components/Tooltip.vue +0 -200
  36. package/ui-library/components/plugin.ts +0 -8
  37. package/ui-library/components/uiProps.ts +0 -11
  38. package/ui-library/components/useUiClasses.ts +0 -159
  39. package/ui-library/module.ts +0 -20
@@ -1,356 +0,0 @@
1
- <script setup lang="ts">
2
- defineOptions({
3
- name: 'UIRadio',
4
- })
5
-
6
- import { computed } from 'vue'
7
-
8
- type LabelPosition =
9
- | 'top'
10
- | 'bottom'
11
- | 'left'
12
- | 'right'
13
-
14
- type RadioSize =
15
- | 'sm'
16
- | 'md'
17
- | 'lg'
18
-
19
- type Rounded =
20
- | 'none'
21
- | 'sm'
22
- | 'md'
23
- | 'lg'
24
- | 'full'
25
-
26
- const props = withDefaults(
27
- defineProps<{
28
- modelValue?:
29
- | string
30
- | number
31
- | boolean
32
- value:
33
- | string
34
- | number
35
- | boolean
36
- label: string
37
- id?: string
38
- name?: string
39
- hint?: string
40
- icon?: string
41
- disable?: boolean
42
- color?: string
43
- size?: RadioSize
44
- rounded?: Rounded
45
- flat?: boolean
46
- bordered?: boolean
47
- borderColor?: string
48
- labelPosition?: LabelPosition
49
- }>(),
50
- {
51
- modelValue: '',
52
- id: undefined,
53
- name: '',
54
- hint: '',
55
- icon: '',
56
- disable: false,
57
- color: 'blue-500',
58
- size: 'md',
59
- rounded: 'full',
60
- flat: false,
61
- bordered: true,
62
- borderColor: 'gray-300',
63
- labelPosition: 'right',
64
- },
65
- )
66
-
67
- const emit = defineEmits<{
68
- (
69
- e: 'update:modelValue',
70
- value:
71
- | string
72
- | number
73
- | boolean,
74
- ): void
75
- }>()
76
-
77
- const isHex = (
78
- val: string,
79
- ): boolean => {
80
- return (
81
- val.startsWith('#') ||
82
- val.startsWith('rgb') ||
83
- val.startsWith('hsl')
84
- )
85
- }
86
-
87
- const isChecked = computed(
88
- () =>
89
- props.modelValue ===
90
- props.value,
91
- )
92
-
93
- const sizeClasses = computed(
94
- () => {
95
- switch (props.size) {
96
- case 'sm':
97
- return {
98
- radio:
99
- 'w-4 h-4',
100
-
101
- icon:
102
- 'text-sm',
103
- }
104
- case 'lg':
105
- return {
106
- radio:
107
- 'w-6 h-6',
108
-
109
- icon:
110
- 'text-lg',
111
- }
112
- case 'md':
113
- default:
114
- return {
115
- radio:
116
- 'w-5 h-5',
117
-
118
- icon:
119
- 'text-base',
120
- }
121
- }
122
- },
123
- )
124
-
125
- const roundedClass = computed(
126
- () => {
127
- const map: Record<
128
- Rounded,
129
- string
130
- > = {
131
- none: 'rounded-none',
132
- sm: 'rounded-sm',
133
- md: 'rounded-md',
134
- lg: 'rounded-lg',
135
- full: 'rounded-full',
136
- }
137
-
138
- return map[props.rounded]
139
- },
140
- )
141
-
142
- const labelPositionClass =
143
- computed(() => {
144
- const map: Record<
145
- LabelPosition,
146
- string
147
- > = {
148
- top: 'flex-col-reverse',
149
- bottom: 'flex-col',
150
- left: 'flex-row-reverse',
151
- right: 'flex-row',
152
- }
153
-
154
- return map[
155
- props.labelPosition
156
- ]
157
- })
158
-
159
- const radioClasses = computed(
160
- () => [
161
- 'inline-flex items-center justify-center border-2 transition-all duration-200 bg-white dark:bg-gray-900',
162
- sizeClasses.value.radio,
163
- roundedClass.value,
164
- props.flat
165
- ? 'shadow-none'
166
- : 'shadow-sm',
167
- props.disable
168
- ? 'opacity-50'
169
- : '',
170
- props.bordered &&
171
- !isHex(
172
- props.borderColor,
173
- )
174
- ? `border-${props.borderColor}`
175
- : '',
176
- isChecked.value &&
177
- !isHex(props.color)
178
- ? `border-${props.color} text-${props.color}`
179
- : '',
180
- !isChecked.value
181
- ? 'border-gray-300'
182
- : '',
183
- ])
184
-
185
- const radioStyle = computed(
186
- () => {
187
- const style: Record<
188
- string,
189
- string
190
- > = {}
191
-
192
- if (
193
- props.bordered &&
194
- isHex(
195
- props.borderColor,
196
- )
197
- ) {
198
- style.borderColor =
199
- props.borderColor
200
- }
201
-
202
- if (
203
- isChecked.value &&
204
- isHex(props.color)
205
- ) {
206
- style.borderColor =
207
- props.color
208
-
209
- style.color =
210
- props.color
211
- }
212
-
213
- return style
214
- },
215
- )
216
-
217
- const iconClasses = computed(
218
- () => [
219
- 'material-icons transition-opacity duration-200',
220
- sizeClasses.value.icon,
221
- isChecked.value
222
- ? 'opacity-100'
223
- : 'opacity-0',
224
- !isHex(props.color)
225
- ? `text-${props.color}`
226
- : '',
227
- ])
228
-
229
- const iconStyle = computed(
230
- () => {
231
- const style: Record<
232
- string,
233
- string
234
- > = {}
235
-
236
- if (
237
- isHex(props.color)
238
- ) {
239
- style.color =
240
- props.color
241
- }
242
- return style
243
- },
244
- )
245
-
246
- const toggle = (): void => {
247
- if (props.disable)
248
- return
249
-
250
- emit(
251
- 'update:modelValue',
252
- props.value,
253
- )
254
- }
255
- </script>
256
- <template>
257
- <div
258
- class="radio-container flex items-center"
259
- >
260
- <input
261
- :id="id"
262
- type="radio"
263
- :name="name"
264
- :value="value"
265
- :checked="
266
- isChecked
267
- "
268
- :disabled="
269
- disable
270
- "
271
- class="sr-only"
272
- @change="toggle"
273
- >
274
-
275
- <label
276
- :for="id"
277
- tabindex="0"
278
- role="radio"
279
- :aria-checked="
280
- isChecked
281
- "
282
- :aria-disabled="
283
- disable
284
- "
285
- :class="[
286
- 'flex items-center cursor-pointer select-none',
287
- labelPositionClass,
288
- {
289
- 'opacity-50 pointer-events-none':
290
- disable,
291
- },
292
- ]"
293
- @click.prevent="
294
- toggle
295
- "
296
- @keydown.enter.prevent="
297
- toggle
298
- "
299
- @keydown.space.prevent="
300
- toggle
301
- "
302
- >
303
- <!-- Radio -->
304
- <span
305
- :class="
306
- radioClasses
307
- "
308
- :style="
309
- radioStyle
310
- "
311
- >
312
- <i
313
- v-if="
314
- icon &&
315
- isChecked
316
- "
317
- :class="
318
- iconClasses
319
- "
320
- :style="
321
- iconStyle
322
- "
323
- >
324
- {{ icon }}
325
- </i>
326
- <span
327
- v-else
328
- class="block m-auto rounded-full"
329
- :class="[!isHex(props.color) && isChecked
330
- ?`bg-${props.color}`:'',
331
- size === 'sm'
332
- ? 'w-2 h-2'
333
- : size === 'lg'
334
- ? 'w-3 h-3'
335
- : 'w-2.5 h-2.5',]
336
- "
337
- :style="isHex(props.color)
338
- ? { backgroundColor: props.color }
339
- : {}"
340
- />
341
- </span>
342
-
343
- <!-- Label -->
344
- <span
345
- class="mx-2 font-medium text-gray-700 dark:text-gray-300"
346
- >
347
- {{ label }}
348
- </span>
349
- </label>
350
- </div>
351
- </template>
352
- <style scoped>
353
- .radio-container {
354
- user-select: none;
355
- }
356
- </style>
@@ -1,43 +0,0 @@
1
- <script setup lang="ts">
2
- defineOptions({
3
- inheritAttrs: false,
4
- })
5
-
6
- import { computed } from 'vue'
7
-
8
- const props = defineProps({
9
- width: { type: String, default: '100%' },
10
- height: { type: String, default: '300px' },
11
-
12
- maxWidth: { type: String, default: '' },
13
- maxHeight: { type: String, default: '' },
14
-
15
- horizontal: { type: Boolean, default: false },
16
- vertical: { type: Boolean, default: true },
17
-
18
- hideScrollbar: { type: Boolean, default: false },
19
- })
20
-
21
- const scrollStyle = computed(() => ({
22
- width: props.width,
23
- height: props.height,
24
- maxWidth: props.maxWidth || undefined,
25
- maxHeight: props.maxHeight || undefined,
26
- }))
27
-
28
- const scrollClass = computed(() => [
29
- props.vertical ? 'overflow-y-auto' : 'overflow-y-hidden',
30
- props.horizontal ? 'overflow-x-auto' : 'overflow-x-hidden',
31
- props.hideScrollbar ? 'scrollbar-hide' : '',
32
- ])
33
- </script>
34
-
35
- <template>
36
- <div
37
- :class="scrollClass"
38
- :style="scrollStyle"
39
- v-bind="$attrs"
40
- >
41
- <slot />
42
- </div>
43
- </template>
@@ -1,309 +0,0 @@
1
- <script setup lang="ts">
2
- defineOptions({
3
- name: 'UISelect',
4
- })
5
-
6
- import {
7
- computed,
8
- ref,
9
- watch,
10
- } from 'vue'
11
-
12
- interface SelectOption {
13
- text: string
14
- value:
15
- | string
16
- | number
17
- | boolean
18
- }
19
-
20
- type Rounded =
21
- | 'none'
22
- | 'sm'
23
- | 'md'
24
- | 'lg'
25
- | 'xl'
26
- | 'full'
27
-
28
- const props = withDefaults(
29
- defineProps<{
30
- filter?: boolean
31
- modelValue?:
32
- | string
33
- | number
34
- | boolean
35
- label: string
36
- id?: string
37
- options: SelectOption[]
38
- placeholder?: string
39
- disabled?: boolean
40
- required?: boolean
41
- hint?: string
42
- flat?: boolean
43
- bordered?: boolean
44
- rounded?: Rounded
45
- borderColor?: string
46
- bgColor?: string
47
- textColor?: string
48
- }>(),
49
- {
50
- filter: false,
51
- modelValue: '',
52
- id: undefined,
53
- placeholder:
54
- 'Search or select...',
55
- disabled: false,
56
- required: false,
57
- hint: '',
58
- flat: false,
59
- bordered: true,
60
- rounded: 'md',
61
- borderColor:
62
- 'gray-300',
63
- bgColor: 'white',
64
- textColor: 'black',
65
- },
66
- )
67
-
68
- const emit = defineEmits<{
69
- (
70
- e: 'update:modelValue',
71
- value:
72
- | string
73
- | number
74
- | boolean,
75
- ): void
76
- }>()
77
-
78
- const searchQuery = ref('')
79
- const showDropdown =
80
- ref(false)
81
-
82
- const isHex = (
83
- val: string,
84
- ): boolean => {
85
- return (
86
- val.startsWith('#') ||
87
- val.startsWith('rgb') ||
88
- val.startsWith('hsl')
89
- )
90
- }
91
-
92
- const roundedClass =
93
- computed(() => {
94
- const map: Record<
95
- Rounded,
96
- string
97
- > = {
98
- none: 'rounded-none',
99
- sm: 'rounded-sm',
100
- md: 'rounded-md',
101
- lg: 'rounded-lg',
102
- xl: 'rounded-xl',
103
- full: 'rounded-full',
104
- }
105
-
106
- return map[props.rounded]
107
- })
108
-
109
- const selectClasses =
110
- computed(() => [
111
- 'block w-full px-3 py-2 transition-all focus:outline-none',
112
- roundedClass.value,
113
- props.flat
114
- ? 'shadow-none'
115
- : 'shadow-sm',
116
- props.bordered
117
- ? !isHex(
118
- props.borderColor,
119
- )
120
- ? `border border-${props.borderColor}`
121
- : 'border'
122
- : 'border-0',
123
- !isHex(props.bgColor)
124
- ? `bg-${props.bgColor}`
125
- : '',
126
- !isHex(
127
- props.textColor,
128
- )
129
- ? `text-${props.textColor}`
130
- : '',
131
- props.disabled
132
- ? 'opacity-50 cursor-not-allowed'
133
- : '',
134
- ])
135
-
136
- const selectStyles =
137
- computed(() => {
138
- const style: Record<
139
- string,
140
- string
141
- > = {}
142
-
143
- if (
144
- isHex(props.bgColor)
145
- ) {
146
- style.backgroundColor =
147
- props.bgColor
148
- }
149
-
150
- if (
151
- isHex(
152
- props.borderColor,
153
- )
154
- ) {
155
- style.borderColor =
156
- props.borderColor
157
- }
158
-
159
- if (
160
- isHex(
161
- props.textColor,
162
- )
163
- ) {
164
- style.color =
165
- props.textColor
166
- }
167
-
168
- return style
169
- })
170
-
171
- const filteredOptions =
172
- computed(() => {
173
- const query =
174
- searchQuery.value.toLowerCase()
175
-
176
- return props.options.filter(
177
- (option) =>
178
- option.text
179
- .toLowerCase()
180
- .includes(query),
181
- )
182
- })
183
-
184
- watch(
185
- () => props.modelValue,
186
- (val) => {
187
- const selected =
188
- props.options.find(
189
- (opt) =>
190
- opt.value === val,
191
- )
192
-
193
- if (selected) {
194
- searchQuery.value =
195
- selected.text
196
- }
197
- },
198
- {
199
- immediate: true,
200
- },
201
- )
202
-
203
- const selectOption = (
204
- option: SelectOption,
205
- ): void => {
206
- searchQuery.value =
207
- option.text
208
-
209
- emit(
210
- 'update:modelValue',
211
- option.value,
212
- )
213
-
214
- showDropdown.value =
215
- false
216
- }
217
-
218
- const handleChange = (
219
- event: Event,
220
- ): void => {
221
- const target =
222
- event.target as HTMLSelectElement
223
-
224
- emit(
225
- 'update:modelValue',
226
- target.value,
227
- )
228
- }
229
-
230
- const handleBlur = (): void => {
231
- setTimeout(() => {
232
- showDropdown.value =
233
- false
234
- }, 100)
235
- }
236
- </script>
237
-
238
- <template>
239
- <div class="relative my-5">
240
- <!-- Label -->
241
- <label v-if="label" :for="id" class="block mb-2 text-sm font-medium text-gray-600 dark:text-gray-300">
242
- {{ label }}
243
- </label>
244
-
245
- <!-- Filterable Select -->
246
- <div v-if="filter" class="relative">
247
- <input v-model="searchQuery
248
- " :placeholder="placeholder
249
- " :disabled="disabled
250
- " :required="required
251
- " :class="selectClasses
252
- " :style="selectStyles
253
- " @focus="
254
- showDropdown = true
255
- " @blur="
256
- handleBlur
257
- " @input="
258
- showDropdown = true
259
- ">
260
-
261
- <!-- Dropdown -->
262
- <ul v-if="
263
- showDropdown
264
- "
265
- class="absolute z-10 mt-1 w-full max-h-48 overflow-y-auto bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-md shadow-lg">
266
- <li v-for="option in filteredOptions" :key="option.value.toString()
267
- " class="px-4 py-2 cursor-pointer hover:bg-gray-100 dark:hover:bg-gray-700" @mousedown.prevent="
268
- selectOption(
269
- option,
270
- )
271
- ">
272
- {{ option.text }}
273
- </li>
274
-
275
- <li v-if="
276
- filteredOptions.length ===
277
- 0
278
- " class="px-4 py-2 text-gray-500">
279
- No results found
280
- </li>
281
- </ul>
282
- </div>
283
-
284
- <!-- Native Select -->
285
- <select v-else :id="id" :value="modelValue
286
- " :disabled="disabled
287
- " :required="required
288
- " :class="selectClasses
289
- " :style="selectStyles
290
- " @change="
291
- handleChange
292
- ">
293
- <option disabled value="">
294
- {{ placeholder }}
295
- </option>
296
-
297
- <option v-for="option in options" :key="option.value.toString()
298
- " :value="option.value
299
- ">
300
- {{ option.text }}
301
- </option>
302
- </select>
303
-
304
- <!-- Hint -->
305
- <p v-if="hint" class="mt-1 text-sm text-gray-500">
306
- {{ hint }}
307
- </p>
308
- </div>
309
- </template>