windly-ui 1.0.2 → 1.0.4

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 (103) hide show
  1. package/{ui-library/dist → dist}/module.json +2 -2
  2. package/dist/module.mjs +33 -0
  3. package/dist/runtime/components/Accordion.d.vue.ts +39 -0
  4. package/dist/runtime/components/Accordion.vue +96 -0
  5. package/dist/runtime/components/Accordion.vue.d.ts +39 -0
  6. package/dist/runtime/components/Alert.d.vue.ts +83 -0
  7. package/dist/runtime/components/Alert.vue +78 -0
  8. package/dist/runtime/components/Alert.vue.d.ts +83 -0
  9. package/dist/runtime/components/Avatar.d.vue.ts +141 -0
  10. package/dist/runtime/components/Avatar.vue +72 -0
  11. package/dist/runtime/components/Avatar.vue.d.ts +141 -0
  12. package/dist/runtime/components/Badge.d.vue.ts +133 -0
  13. package/dist/runtime/components/Badge.vue +99 -0
  14. package/dist/runtime/components/Badge.vue.d.ts +133 -0
  15. package/dist/runtime/components/Breadcrumbs.d.vue.ts +83 -0
  16. package/dist/runtime/components/Breadcrumbs.vue +116 -0
  17. package/dist/runtime/components/Breadcrumbs.vue.d.ts +83 -0
  18. package/dist/runtime/components/Button.d.vue.ts +208 -0
  19. package/dist/runtime/components/Button.vue +126 -0
  20. package/dist/runtime/components/Button.vue.d.ts +208 -0
  21. package/dist/runtime/components/Card.d.vue.ts +83 -0
  22. package/dist/runtime/components/Card.vue +71 -0
  23. package/dist/runtime/components/Card.vue.d.ts +83 -0
  24. package/dist/runtime/components/Checkbox.d.vue.ts +190 -0
  25. package/dist/runtime/components/Checkbox.vue +125 -0
  26. package/dist/runtime/components/Checkbox.vue.d.ts +190 -0
  27. package/dist/runtime/components/CodeBlock.d.vue.ts +16 -0
  28. package/dist/runtime/components/CodeBlock.vue +75 -0
  29. package/dist/runtime/components/CodeBlock.vue.d.ts +16 -0
  30. package/dist/runtime/components/ColorPicker.d.vue.ts +91 -0
  31. package/dist/runtime/components/ColorPicker.vue +244 -0
  32. package/dist/runtime/components/ColorPicker.vue.d.ts +91 -0
  33. package/dist/runtime/components/Date.d.vue.ts +137 -0
  34. package/dist/runtime/components/Date.vue +201 -0
  35. package/dist/runtime/components/Date.vue.d.ts +137 -0
  36. package/dist/runtime/components/Dialog.d.vue.ts +63 -0
  37. package/dist/runtime/components/Dialog.vue +85 -0
  38. package/dist/runtime/components/Dialog.vue.d.ts +63 -0
  39. package/dist/runtime/components/Divider.d.vue.ts +51 -0
  40. package/dist/runtime/components/Divider.vue +52 -0
  41. package/dist/runtime/components/Divider.vue.d.ts +51 -0
  42. package/dist/runtime/components/Drawer.d.vue.ts +30 -0
  43. package/dist/runtime/components/Drawer.vue +43 -0
  44. package/dist/runtime/components/Drawer.vue.d.ts +30 -0
  45. package/dist/runtime/components/Dropdown.d.vue.ts +34 -0
  46. package/dist/runtime/components/Dropdown.vue +127 -0
  47. package/dist/runtime/components/Dropdown.vue.d.ts +34 -0
  48. package/dist/runtime/components/FileUploader.d.vue.ts +65 -0
  49. package/dist/runtime/components/FileUploader.vue +358 -0
  50. package/dist/runtime/components/FileUploader.vue.d.ts +65 -0
  51. package/dist/runtime/components/Icon.d.vue.ts +41 -0
  52. package/dist/runtime/components/Icon.vue +66 -0
  53. package/dist/runtime/components/Icon.vue.d.ts +41 -0
  54. package/dist/runtime/components/Image.d.vue.ts +77 -0
  55. package/dist/runtime/components/Image.vue +61 -0
  56. package/dist/runtime/components/Image.vue.d.ts +77 -0
  57. package/dist/runtime/components/Input.d.vue.ts +68 -0
  58. package/dist/runtime/components/Input.vue +241 -0
  59. package/dist/runtime/components/Input.vue.d.ts +68 -0
  60. package/dist/runtime/components/Radio.d.vue.ts +41 -0
  61. package/dist/runtime/components/Radio.vue +222 -0
  62. package/dist/runtime/components/Radio.vue.d.ts +41 -0
  63. package/dist/runtime/components/ScrollArea.d.vue.ts +79 -0
  64. package/dist/runtime/components/ScrollArea.vue +36 -0
  65. package/dist/runtime/components/ScrollArea.vue.d.ts +79 -0
  66. package/dist/runtime/components/Select.d.vue.ts +51 -0
  67. package/dist/runtime/components/Select.vue +271 -0
  68. package/dist/runtime/components/Select.vue.d.ts +51 -0
  69. package/dist/runtime/components/Stepper.d.vue.ts +46 -0
  70. package/dist/runtime/components/Stepper.vue +218 -0
  71. package/dist/runtime/components/Stepper.vue.d.ts +46 -0
  72. package/dist/runtime/components/TabPanel.d.vue.ts +17 -0
  73. package/dist/runtime/components/TabPanel.vue +21 -0
  74. package/dist/runtime/components/TabPanel.vue.d.ts +17 -0
  75. package/dist/runtime/components/Table.d.vue.ts +40 -0
  76. package/dist/runtime/components/Table.vue +92 -0
  77. package/dist/runtime/components/Table.vue.d.ts +40 -0
  78. package/dist/runtime/components/Tabs.d.vue.ts +20 -0
  79. package/dist/runtime/components/Tabs.vue +62 -0
  80. package/dist/runtime/components/Tabs.vue.d.ts +20 -0
  81. package/dist/runtime/components/Textarea.d.vue.ts +208 -0
  82. package/dist/runtime/components/Textarea.vue +185 -0
  83. package/dist/runtime/components/Textarea.vue.d.ts +208 -0
  84. package/dist/runtime/components/Toggle.d.vue.ts +36 -0
  85. package/dist/runtime/components/Toggle.vue +173 -0
  86. package/dist/runtime/components/Toggle.vue.d.ts +36 -0
  87. package/dist/runtime/components/Tooltip.d.vue.ts +63 -0
  88. package/dist/runtime/components/Tooltip.vue +144 -0
  89. package/dist/runtime/components/Tooltip.vue.d.ts +63 -0
  90. package/dist/runtime/components/uiProps.d.ts +38 -0
  91. package/dist/runtime/components/uiProps.js +11 -0
  92. package/dist/runtime/components/useUiClasses.d.ts +43 -0
  93. package/dist/runtime/components/useUiClasses.js +124 -0
  94. package/dist/runtime/composables/plugin.d.ts +2 -0
  95. package/dist/runtime/composables/plugin.js +3 -0
  96. package/dist/runtime/tailwind-color.d.ts +2 -0
  97. package/dist/runtime/tailwind-color.js +5859 -0
  98. package/package.json +12 -46
  99. package/LICENSE +0 -21
  100. package/README.md +0 -232
  101. package/ui-library/dist/module.mjs +0 -22
  102. /package/{ui-library/dist → dist}/module.d.mts +0 -0
  103. /package/{ui-library/dist → dist}/types.d.mts +0 -0
@@ -0,0 +1,271 @@
1
+ <script setup>
2
+ defineOptions({
3
+ name: "UISelect"
4
+ });
5
+ import { computed, ref, watch } from "vue";
6
+ const props = defineProps({
7
+ modelValue: { type: [String, Number, Boolean], required: false, default: "" },
8
+ label: { type: String, required: false, default: "" },
9
+ hint: { type: String, required: false, default: "" },
10
+ placeholder: { type: String, required: false, default: "Select..." },
11
+ filter: { type: Boolean, required: false, default: false },
12
+ size: { type: String, required: false, default: "md" },
13
+ color: { type: String, required: false, default: "" },
14
+ rounded: { type: String, required: false, default: "md" },
15
+ dense: { type: Boolean, required: false, default: false },
16
+ width: { type: String, required: false, default: "" },
17
+ outlined: { type: Boolean, required: false, default: false },
18
+ borderless: { type: Boolean, required: false, default: false },
19
+ flat: { type: Boolean, required: false, default: false },
20
+ disabled: { type: Boolean, required: false, default: false },
21
+ readonly: { type: Boolean, required: false, default: false },
22
+ required: { type: Boolean, required: false, default: false },
23
+ id: { type: String, required: false, default: void 0 },
24
+ options: { type: Array, required: true }
25
+ });
26
+ const emit = defineEmits(["update:modelValue"]);
27
+ const showDropdown = ref(false);
28
+ const searchQuery = ref("");
29
+ const isHex = (val) => val.startsWith("#");
30
+ const roundedMap = {
31
+ none: "rounded-none",
32
+ sm: "rounded-sm",
33
+ md: "rounded-md",
34
+ lg: "rounded-lg",
35
+ xl: "rounded-xl",
36
+ full: "rounded-full"
37
+ };
38
+ const computedClass = computed(() => {
39
+ let classes = "input block transition-all duration-300";
40
+ if (props.borderless) {
41
+ classes += " border-none bg-transparent";
42
+ } else if (props.outlined) {
43
+ classes += " border";
44
+ } else {
45
+ classes += " border-0 border-b";
46
+ }
47
+ classes += ` ${roundedMap[props.rounded] ?? roundedMap.md}`;
48
+ if (!props.flat) {
49
+ classes += " shadow-sm";
50
+ }
51
+ if (props.disabled) {
52
+ classes += " opacity-50 cursor-not-allowed";
53
+ }
54
+ if (props.readonly) {
55
+ classes += " pointer-events-none";
56
+ }
57
+ switch (props.size) {
58
+ case "sm":
59
+ classes += " text-sm";
60
+ break;
61
+ case "lg":
62
+ classes += " text-lg";
63
+ break;
64
+ default:
65
+ classes += " text-base";
66
+ }
67
+ if (props.color && !isHex(props.color)) {
68
+ classes += ` border-${props.color} focus:ring-${props.color}`;
69
+ }
70
+ if (props.width && !CSS.supports(
71
+ "width",
72
+ props.width
73
+ )) {
74
+ classes += ` w-${props.width}`;
75
+ }
76
+ if (!props.width) {
77
+ classes += " w-full";
78
+ }
79
+ if (props.modelValue !== "" && props.modelValue !== null && props.modelValue !== void 0) {
80
+ classes += " has-value";
81
+ }
82
+ return classes;
83
+ });
84
+ const computedStyle = computed(() => {
85
+ const styles = {};
86
+ if (props.width && CSS.supports(
87
+ "width",
88
+ props.width
89
+ )) {
90
+ styles.width = props.width;
91
+ }
92
+ if (props.color && isHex(props.color)) {
93
+ styles["--tw-ring-color"] = props.color;
94
+ styles.borderColor = props.color;
95
+ }
96
+ return styles;
97
+ });
98
+ const filteredOptions = computed(() => {
99
+ const query = searchQuery.value.toLowerCase();
100
+ return props.options.filter(
101
+ (option) => option.text.toLowerCase().includes(query)
102
+ );
103
+ });
104
+ watch(
105
+ () => props.modelValue,
106
+ (value) => {
107
+ const selected = props.options.find(
108
+ (o) => o.value === value
109
+ );
110
+ searchQuery.value = selected?.text ?? "";
111
+ },
112
+ {
113
+ immediate: true
114
+ }
115
+ );
116
+ function selectOption(option) {
117
+ searchQuery.value = option.text;
118
+ emit(
119
+ "update:modelValue",
120
+ option.value
121
+ );
122
+ showDropdown.value = false;
123
+ }
124
+ function handleChange(event) {
125
+ const target = event.target;
126
+ const selected = props.options.find(
127
+ (option) => String(option.value) === target.value
128
+ );
129
+ if (selected) {
130
+ emit(
131
+ "update:modelValue",
132
+ selected.value
133
+ );
134
+ }
135
+ }
136
+ function handleBlur() {
137
+ setTimeout(() => {
138
+ showDropdown.value = false;
139
+ }, 150);
140
+ }
141
+ const inputAttrs = computed(() => {
142
+ const attrs = {};
143
+ if (props.placeholder)
144
+ attrs.placeholder = props.placeholder;
145
+ if (props.disabled)
146
+ attrs.disabled = props.disabled;
147
+ if (props.readonly)
148
+ attrs.readonly = props.readonly;
149
+ if (props.required)
150
+ attrs.required = props.required;
151
+ return attrs;
152
+ });
153
+ </script>
154
+
155
+ <template>
156
+ <div
157
+ class="select-container"
158
+ :class="{
159
+ dense: !outlined || dense,
160
+ [`input-${size}`]: size
161
+ }"
162
+ >
163
+ <!-- Filterable Select -->
164
+ <div
165
+ v-if="filter"
166
+ class="relative"
167
+ >
168
+ <input
169
+ v-model="searchQuery"
170
+ v-bind="inputAttrs"
171
+ :class="computedClass"
172
+ :style="computedStyle"
173
+ @focus="showDropdown = true"
174
+ @input="showDropdown = true"
175
+ @blur="handleBlur"
176
+ />
177
+
178
+ <label
179
+ class="label"
180
+ :class="
181
+ color && !isHex(color) ? `text-${color}` : ''
182
+ "
183
+ :style="
184
+ color ? {
185
+ color: isHex(color) ? color : void 0
186
+ } : {
187
+ color: '#9ca3af'
188
+ }
189
+ "
190
+ >
191
+ {{ label }}
192
+ </label>
193
+
194
+ <!-- Dropdown -->
195
+ <ul
196
+ v-if="showDropdown"
197
+ class="absolute left-0 right-0 z-50 mt-1 max-h-60 overflow-y-auto rounded-md border bg-white shadow-lg"
198
+ >
199
+ <li
200
+ v-for="option in filteredOptions"
201
+ :key="option.value.toString()"
202
+ class="cursor-pointer px-3 py-2 transition-colors hover:bg-gray-100"
203
+ @mousedown.prevent="selectOption(option)"
204
+ >
205
+ {{ option.text }}
206
+ </li>
207
+
208
+ <li
209
+ v-if="filteredOptions.length === 0"
210
+ class="px-3 py-2 text-sm text-gray-500"
211
+ >
212
+ No results found
213
+ </li>
214
+ </ul>
215
+ </div>
216
+
217
+ <!-- Native Select -->
218
+ <template v-else>
219
+ <select
220
+ :id="id"
221
+ :value="modelValue"
222
+ v-bind="inputAttrs"
223
+ :class="computedClass"
224
+ :style="computedStyle"
225
+ @change="handleChange"
226
+ >
227
+ <option
228
+ disabled
229
+ value=""
230
+ >
231
+ {{ placeholder }}
232
+ </option>
233
+
234
+ <option
235
+ v-for="option in options"
236
+ :key="option.value.toString()"
237
+ :value="option.value"
238
+ >
239
+ {{ option.text }}
240
+ </option>
241
+ </select>
242
+
243
+ <label
244
+ class="label"
245
+ :class="
246
+ color && !isHex(color) ? `text-${color}` : ''
247
+ "
248
+ :style="
249
+ color ? {
250
+ color: isHex(color) ? color : void 0
251
+ } : {
252
+ color: '#9ca3af'
253
+ }
254
+ "
255
+ >
256
+ {{ label }}
257
+ </label>
258
+ </template>
259
+
260
+ <p
261
+ v-if="hint"
262
+ class="hint-text"
263
+ >
264
+ {{ hint }}
265
+ </p>
266
+ </div>
267
+ </template>
268
+
269
+ <style scoped>
270
+ .select-container{margin:20px 0 10px;position:relative}.select-container.dense{margin:10px 0}.input{background:transparent;padding:10px;width:100%}.select-container.dense .input{padding:6px 10px}.input:focus{outline:none}select.input{appearance:none;-webkit-appearance:none;-moz-appearance:none;cursor:pointer;padding-right:2.5rem}.label{left:10px;padding:0 5px;pointer-events:none;position:absolute;top:50%;transform:translateY(-50%);transition:top .2s ease,font-size .2s ease,color .2s ease,transform .2s ease}.input:-moz-placeholder+.label{left:5px;top:-20px;transform:none;z-index:2}.input.has-value+.label,.input:focus+.label,.input:placeholder-shown+.label,select.input.has-value+.label,select.input:focus+.label{left:5px;top:-20px;transform:none;z-index:2}.select-container.dense .input.has-value+.label,.select-container.dense .input:focus+.label,.select-container.dense select.input.has-value+.label,.select-container.dense select.input:focus+.label{top:-10px}.select-container.input-lg .input.has-value+.label,.select-container.input-lg .input:focus+.label,.select-container.input-lg select.input.has-value+.label,.select-container.input-lg select.input:focus+.label{top:-24px}.select-container.input-sm .label{font-size:14px}.select-container.input-md .label{font-size:16px}.select-container.input-lg .label{font-size:18px}.select-container.input-sm .input.has-value+.label,.select-container.input-sm .input:focus+.label,.select-container.input-sm select.input.has-value+.label,.select-container.input-sm select.input:focus+.label{font-size:12px}.select-container.input-md .input.has-value+.label,.select-container.input-md .input:focus+.label,.select-container.input-md select.input.has-value+.label,.select-container.input-md select.input:focus+.label{font-size:14px}.select-container.input-lg .input.has-value+.label,.select-container.input-lg .input:focus+.label,.select-container.input-lg select.input.has-value+.label,.select-container.input-lg select.input:focus+.label{font-size:16px}.hint-text{color:#6b7280;font-size:12px;margin-left:5px;margin-top:4px}ul{background:#fff;border:1px solid #d1d5db;border-radius:.5rem;box-shadow:0 10px 15px -3px rgba(0,0,0,.1),0 4px 6px -4px rgba(0,0,0,.1);max-height:240px;overflow-y:auto}li{transition:background-color .2s}li:hover{background:#f3f4f6}.dark .label,.dark ul{background:#1f2937}.dark ul{border-color:#374151}.dark li:hover{background:#374151}.dark .hint-text{color:#9ca3af}
271
+ </style>
@@ -0,0 +1,51 @@
1
+ interface SelectOption {
2
+ text: string;
3
+ value: string | number | boolean;
4
+ }
5
+ type Rounded = "none" | "sm" | "md" | "lg" | "xl" | "full";
6
+ type Size = "sm" | "md" | "lg";
7
+ type __VLS_Props = {
8
+ modelValue?: string | number | boolean;
9
+ label?: string;
10
+ hint?: string;
11
+ placeholder?: string;
12
+ filter?: boolean;
13
+ size?: Size;
14
+ color?: string;
15
+ rounded?: Rounded;
16
+ dense?: boolean;
17
+ width?: string;
18
+ outlined?: boolean;
19
+ borderless?: boolean;
20
+ flat?: boolean;
21
+ disabled?: boolean;
22
+ readonly?: boolean;
23
+ required?: boolean;
24
+ id?: string;
25
+ options: SelectOption[];
26
+ };
27
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
28
+ "update:modelValue": (value: string | number | boolean) => any;
29
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
30
+ "onUpdate:modelValue"?: ((value: string | number | boolean) => any) | undefined;
31
+ }>, {
32
+ modelValue: string | number | boolean;
33
+ disabled: boolean;
34
+ dense: boolean;
35
+ label: string;
36
+ filter: boolean;
37
+ required: boolean;
38
+ color: string;
39
+ rounded: Rounded;
40
+ size: Size;
41
+ flat: boolean;
42
+ id: string;
43
+ placeholder: string;
44
+ width: string;
45
+ readonly: boolean;
46
+ hint: string;
47
+ outlined: boolean;
48
+ borderless: boolean;
49
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
50
+ declare const _default: typeof __VLS_export;
51
+ export default _default;
@@ -0,0 +1,46 @@
1
+ interface StepItem {
2
+ label: string;
3
+ name?: string;
4
+ icon?: string;
5
+ iconColor?: string;
6
+ }
7
+ type Step = string | StepItem;
8
+ type __VLS_Props = {
9
+ steps: Step[];
10
+ modelValue?: number;
11
+ vertical?: boolean;
12
+ completedColor?: string;
13
+ activeColor?: string;
14
+ inactiveColor?: string;
15
+ connectorCompletedColor?: string;
16
+ connectorInactiveColor?: string;
17
+ inactiveSteps?: number[];
18
+ };
19
+ declare var __VLS_1: {
20
+ step: number;
21
+ };
22
+ type __VLS_Slots = {} & {
23
+ default?: (props: typeof __VLS_1) => any;
24
+ };
25
+ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
26
+ "update:modelValue": (value: number) => any;
27
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
28
+ "onUpdate:modelValue"?: ((value: number) => any) | undefined;
29
+ }>, {
30
+ modelValue: number;
31
+ activeColor: string;
32
+ vertical: boolean;
33
+ completedColor: string;
34
+ inactiveColor: string;
35
+ connectorCompletedColor: string;
36
+ connectorInactiveColor: string;
37
+ inactiveSteps: number[];
38
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
39
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
40
+ declare const _default: typeof __VLS_export;
41
+ export default _default;
42
+ type __VLS_WithSlots<T, S> = T & {
43
+ new (): {
44
+ $slots: S;
45
+ };
46
+ };
@@ -0,0 +1,218 @@
1
+ <script setup>
2
+ import { computed } from "vue";
3
+ const props = defineProps({
4
+ steps: { type: Array, required: true },
5
+ modelValue: { type: Number, required: false, default: 0 },
6
+ vertical: { type: Boolean, required: false, default: false },
7
+ completedColor: { type: String, required: false, default: "green-500" },
8
+ activeColor: { type: String, required: false, default: "blue-500" },
9
+ inactiveColor: { type: String, required: false, default: "gray-300" },
10
+ connectorCompletedColor: { type: String, required: false, default: "green-500" },
11
+ connectorInactiveColor: { type: String, required: false, default: "gray-300" },
12
+ inactiveSteps: { type: Array, required: false, default: () => [] }
13
+ });
14
+ const emit = defineEmits(["update:modelValue"]);
15
+ const currentStep = computed(
16
+ () => props.modelValue
17
+ );
18
+ const normalizedSteps = computed(
19
+ () => props.steps.map((step) => {
20
+ if (typeof step === "string") {
21
+ return {
22
+ label: step
23
+ };
24
+ }
25
+ return step;
26
+ })
27
+ );
28
+ const isHex = (val) => val.startsWith("#");
29
+ const isInactiveStep = (index) => {
30
+ return props.inactiveSteps.includes(
31
+ index
32
+ );
33
+ };
34
+ const stepState = (index) => {
35
+ if (isInactiveStep(index)) {
36
+ return "inactive";
37
+ }
38
+ if (index < currentStep.value) {
39
+ return "completed";
40
+ }
41
+ if (index === currentStep.value) {
42
+ return "active";
43
+ }
44
+ return "pending";
45
+ };
46
+ const stepClasses = (index) => {
47
+ const state = stepState(index);
48
+ switch (state) {
49
+ case "completed":
50
+ return [
51
+ !isHex(
52
+ props.completedColor
53
+ ) ? `bg-${props.completedColor}` : "",
54
+ "text-white"
55
+ ];
56
+ case "active":
57
+ return [
58
+ !isHex(
59
+ props.activeColor
60
+ ) ? `bg-${props.activeColor}` : "",
61
+ "text-white"
62
+ ];
63
+ case "inactive":
64
+ return [
65
+ !isHex(
66
+ props.inactiveColor
67
+ ) ? `bg-${props.inactiveColor}` : "",
68
+ "text-gray-500 opacity-60 cursor-not-allowed"
69
+ ];
70
+ case "pending":
71
+ default:
72
+ return [
73
+ !isHex(
74
+ props.inactiveColor
75
+ ) ? `bg-${props.inactiveColor}` : "",
76
+ "text-gray-600"
77
+ ];
78
+ }
79
+ };
80
+ const stepStyle = (index) => {
81
+ const style = {};
82
+ const state = stepState(index);
83
+ const colorMap = {
84
+ completed: props.completedColor,
85
+ active: props.activeColor,
86
+ inactive: props.inactiveColor,
87
+ pending: props.inactiveColor
88
+ };
89
+ const color = colorMap[state];
90
+ if (isHex(color)) {
91
+ style.backgroundColor = color;
92
+ }
93
+ return style;
94
+ };
95
+ const connectorClasses = (index) => {
96
+ const completed = index < currentStep.value && !isInactiveStep(index + 1);
97
+ const color = completed ? props.connectorCompletedColor : props.connectorInactiveColor;
98
+ return [
99
+ !isHex(color) ? `bg-${color}` : ""
100
+ ];
101
+ };
102
+ const connectorStyle = (index) => {
103
+ const style = {};
104
+ const completed = index < currentStep.value && !isInactiveStep(index + 1);
105
+ const color = completed ? props.connectorCompletedColor : props.connectorInactiveColor;
106
+ if (isHex(color)) {
107
+ style.backgroundColor = color;
108
+ }
109
+ return style;
110
+ };
111
+ const labelClasses = (index) => {
112
+ if (isInactiveStep(index)) {
113
+ return "text-gray-400 opacity-60 cursor-not-allowed";
114
+ }
115
+ if (index === currentStep.value) {
116
+ return "text-black dark:text-white";
117
+ }
118
+ return "text-gray-500";
119
+ };
120
+ const navigate = (index) => {
121
+ if (isInactiveStep(index)) {
122
+ return;
123
+ }
124
+ emit(
125
+ "update:modelValue",
126
+ index
127
+ );
128
+ };
129
+ </script>
130
+
131
+ <template>
132
+ <div :class="{
133
+ flex: vertical,
134
+ block: !vertical
135
+ }">
136
+ <!-- Steps -->
137
+ <div :class="{
138
+ 'flex flex-col items-start': vertical,
139
+ 'flex items-start justify-between': !vertical
140
+ }">
141
+ <div v-for="(
142
+ step, index
143
+ ) in normalizedSteps" :key="index" :class="{
144
+ 'relative flex-1 flex items-start': !vertical,
145
+ 'relative flex flex-col items-start': vertical
146
+ }">
147
+ <div :class="{
148
+ 'flex items-center': vertical,
149
+ 'flex flex-col items-center': !vertical
150
+ }">
151
+ <!-- Step Indicator -->
152
+ <div @click="
153
+ navigate(index)
154
+ " :class="[
155
+ 'flex items-center justify-center w-10 h-10 rounded-full font-bold z-10 transition-colors',
156
+ stepClasses(index)
157
+ ]" :style="
158
+ stepStyle(index)
159
+ ">
160
+ <template v-if="step.icon">
161
+ <span class="material-icons">
162
+ {{ step.icon }}
163
+ </span>
164
+ </template>
165
+
166
+ <template v-else>
167
+ {{ index + 1 }}
168
+ </template>
169
+ </div>
170
+
171
+ <!-- Label -->
172
+ <div class="text-center text-sm font-medium mx-2" :class="[
173
+ vertical ? 'ml-4' : 'mt-2',
174
+ labelClasses(index)
175
+ ]" @click="
176
+ navigate(index)
177
+ ">
178
+ {{ step.label }}
179
+ </div>
180
+ </div>
181
+
182
+ <!-- Connector -->
183
+ <div v-if="
184
+ index !== normalizedSteps.length - 1
185
+ " :class="{
186
+ 'flex-1 h-[1px] mt-5 relative': !vertical,
187
+ 'w-[1px] h-16 ml-5 relative': vertical
188
+ }">
189
+ <div class="absolute w-full h-full" :class="
190
+ connectorClasses(
191
+ index
192
+ )
193
+ " :style="[
194
+ connectorStyle(
195
+ index
196
+ ),
197
+ {
198
+ top: vertical ? '50%' : '',
199
+ transform: 'translateY(-50%)'
200
+ }
201
+ ]" />
202
+ </div>
203
+ </div>
204
+ </div>
205
+
206
+ <!-- Content -->
207
+ <div :class="{
208
+ 'ml-4': vertical,
209
+ 'mt-4': !vertical
210
+ }">
211
+ <slot :step="currentStep" />
212
+ </div>
213
+ </div>
214
+ </template>
215
+
216
+ <style scoped>
217
+ .material-icons{font-size:1.5rem}
218
+ </style>
@@ -0,0 +1,46 @@
1
+ interface StepItem {
2
+ label: string;
3
+ name?: string;
4
+ icon?: string;
5
+ iconColor?: string;
6
+ }
7
+ type Step = string | StepItem;
8
+ type __VLS_Props = {
9
+ steps: Step[];
10
+ modelValue?: number;
11
+ vertical?: boolean;
12
+ completedColor?: string;
13
+ activeColor?: string;
14
+ inactiveColor?: string;
15
+ connectorCompletedColor?: string;
16
+ connectorInactiveColor?: string;
17
+ inactiveSteps?: number[];
18
+ };
19
+ declare var __VLS_1: {
20
+ step: number;
21
+ };
22
+ type __VLS_Slots = {} & {
23
+ default?: (props: typeof __VLS_1) => any;
24
+ };
25
+ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
26
+ "update:modelValue": (value: number) => any;
27
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
28
+ "onUpdate:modelValue"?: ((value: number) => any) | undefined;
29
+ }>, {
30
+ modelValue: number;
31
+ activeColor: string;
32
+ vertical: boolean;
33
+ completedColor: string;
34
+ inactiveColor: string;
35
+ connectorCompletedColor: string;
36
+ connectorInactiveColor: string;
37
+ inactiveSteps: number[];
38
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
39
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
40
+ declare const _default: typeof __VLS_export;
41
+ export default _default;
42
+ type __VLS_WithSlots<T, S> = T & {
43
+ new (): {
44
+ $slots: S;
45
+ };
46
+ };
@@ -0,0 +1,17 @@
1
+ type __VLS_Props = {
2
+ name: string;
3
+ label: string;
4
+ };
5
+ declare var __VLS_1: {};
6
+ type __VLS_Slots = {} & {
7
+ default?: (props: typeof __VLS_1) => any;
8
+ };
9
+ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
10
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
11
+ declare const _default: typeof __VLS_export;
12
+ export default _default;
13
+ type __VLS_WithSlots<T, S> = T & {
14
+ new (): {
15
+ $slots: S;
16
+ };
17
+ };
@@ -0,0 +1,21 @@
1
+ <template>
2
+ <div v-show="isActive">
3
+ <slot />
4
+ </div>
5
+ </template>
6
+
7
+ <script setup>
8
+ import { inject, computed, onMounted } from "vue";
9
+ const props = defineProps({
10
+ name: { type: String, required: true },
11
+ label: { type: String, required: true }
12
+ });
13
+ const tabs = inject("tabs");
14
+ onMounted(() => {
15
+ tabs?.registerTab({
16
+ name: props.name,
17
+ label: props.label
18
+ });
19
+ });
20
+ const isActive = computed(() => tabs?.modelValue.value === props.name);
21
+ </script>
@@ -0,0 +1,17 @@
1
+ type __VLS_Props = {
2
+ name: string;
3
+ label: string;
4
+ };
5
+ declare var __VLS_1: {};
6
+ type __VLS_Slots = {} & {
7
+ default?: (props: typeof __VLS_1) => any;
8
+ };
9
+ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
10
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
11
+ declare const _default: typeof __VLS_export;
12
+ export default _default;
13
+ type __VLS_WithSlots<T, S> = T & {
14
+ new (): {
15
+ $slots: S;
16
+ };
17
+ };