vueless 1.4.12-beta.2 → 1.4.12-beta.21
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/README.md +1 -1
- package/composables/useUI.ts +19 -1
- package/index.d.ts +128 -0
- package/index.ts +128 -0
- package/package.json +10 -9
- package/ui.button/config.ts +1 -1
- package/ui.button-link/config.ts +1 -1
- package/ui.button-toggle/UToggle.vue +6 -4
- package/ui.button-toggle/storybook/stories.ts +4 -1
- package/ui.button-toggle/tests/UToggle.test-d.ts +48 -0
- package/ui.button-toggle/tests/UToggleTypes.vue +55 -0
- package/ui.button-toggle/types.ts +18 -6
- package/ui.container-accordion/types.ts +5 -2
- package/ui.container-collapsible/config.ts +1 -1
- package/ui.container-drawer/tests/UDrawer.test.ts +10 -17
- package/ui.container-modal/tests/UModal.test.ts +10 -17
- package/ui.data-list/UDataList.vue +48 -17
- package/ui.data-list/config.ts +2 -2
- package/ui.data-list/storybook/stories.ts +5 -2
- package/ui.data-list/tests/UDataList.test-d.ts +76 -0
- package/ui.data-list/tests/UDataList.test.ts +52 -3
- package/ui.data-list/tests/UDataListTypes.vue +110 -0
- package/ui.data-list/types.ts +37 -5
- package/ui.data-table/UTable.vue +202 -24
- package/ui.data-table/UTableRow.vue +4 -3
- package/ui.data-table/config.ts +11 -2
- package/ui.data-table/storybook/stories.ts +34 -1
- package/ui.data-table/tests/UTable.test-d.ts +179 -0
- package/ui.data-table/tests/UTable.test.ts +85 -7
- package/ui.data-table/tests/UTableEmptyColumnsTypes.vue +27 -0
- package/ui.data-table/tests/UTableTypes.vue +193 -0
- package/ui.data-table/types.ts +106 -9
- package/ui.data-table/utilTable.ts +1 -1
- package/ui.dropdown/UDropdown.vue +19 -8
- package/ui.dropdown/storybook/stories.ts +4 -1
- package/ui.dropdown/tests/UDropdown.test-d.ts +61 -0
- package/ui.dropdown/tests/UDropdown.test.ts +8 -1
- package/ui.dropdown/tests/UDropdownTypes.vue +111 -0
- package/ui.dropdown/types.ts +27 -3
- package/ui.dropdown-badge/UDropdownBadge.vue +9 -4
- package/ui.dropdown-badge/storybook/stories.ts +6 -1
- package/ui.dropdown-badge/tests/UDropdownBadge.test-d.ts +55 -0
- package/ui.dropdown-badge/tests/UDropdownBadge.test.ts +8 -1
- package/ui.dropdown-badge/tests/UDropdownBadgeTypes.vue +107 -0
- package/ui.dropdown-badge/types.ts +17 -3
- package/ui.dropdown-button/UDropdownButton.vue +9 -4
- package/ui.dropdown-button/storybook/stories.ts +6 -1
- package/ui.dropdown-button/tests/UDropdownButton.test-d.ts +57 -0
- package/ui.dropdown-button/tests/UDropdownButton.test.ts +8 -1
- package/ui.dropdown-button/tests/UDropdownButtonTypes.vue +107 -0
- package/ui.dropdown-button/types.ts +17 -3
- package/ui.dropdown-link/UDropdownLink.vue +9 -4
- package/ui.dropdown-link/config.ts +1 -1
- package/ui.dropdown-link/storybook/stories.ts +4 -1
- package/ui.dropdown-link/tests/UDropdownLink.test-d.ts +55 -0
- package/ui.dropdown-link/tests/UDropdownLink.test.ts +8 -1
- package/ui.dropdown-link/tests/UDropdownLinkTypes.vue +107 -0
- package/ui.dropdown-link/types.ts +17 -3
- package/ui.form-calendar/config.ts +1 -1
- package/ui.form-checkbox/config.ts +1 -1
- package/ui.form-checkbox/tests/UCheckbox.test.ts +4 -4
- package/ui.form-checkbox/types.ts +4 -2
- package/ui.form-checkbox-group/UCheckboxGroup.vue +8 -2
- package/ui.form-date-picker/UDatePicker.vue +11 -1
- package/ui.form-date-picker/tests/UDatePicker.test.ts +47 -0
- package/ui.form-input/UInput.vue +1 -0
- package/ui.form-input/config.ts +1 -1
- package/ui.form-input/tests/UInput.test.ts +16 -0
- package/ui.form-input-file/config.ts +1 -1
- package/ui.form-listbox/UListbox.vue +29 -12
- package/ui.form-listbox/config.ts +1 -1
- package/ui.form-listbox/storybook/stories.ts +4 -1
- package/ui.form-listbox/tests/UListbox.test-d.ts +63 -0
- package/ui.form-listbox/tests/UListboxTypes.vue +107 -0
- package/ui.form-listbox/types.ts +34 -2
- package/ui.form-radio/config.ts +1 -1
- package/ui.form-radio-group/URadioGroup.vue +15 -3
- package/ui.form-radio-group/config.ts +8 -3
- package/ui.form-radio-group/types.ts +2 -3
- package/ui.form-select/USelect.vue +49 -17
- package/ui.form-select/config.ts +4 -4
- package/ui.form-select/storybook/stories.ts +4 -1
- package/ui.form-select/tests/USelect.test-d.ts +76 -0
- package/ui.form-select/tests/USelect.test.ts +65 -1
- package/ui.form-select/tests/USelectTypes.vue +113 -0
- package/ui.form-select/types.ts +55 -4
- package/ui.form-switch/USwitch.vue +13 -12
- package/ui.form-switch/config.ts +2 -1
- package/ui.form-switch/tests/USwitch.test.ts +151 -0
- package/ui.form-textarea/config.ts +1 -1
- package/ui.image-avatar/types.ts +5 -2
- package/ui.image-avatar-group/types.ts +5 -2
- package/ui.image-icon/UIcon.vue +3 -2
- package/ui.image-icon/types.ts +2 -2
- package/ui.navigation-breadcrumbs/types.ts +5 -2
- package/ui.navigation-tab/UTab.vue +14 -9
- package/ui.navigation-tab/tests/UTab.test.ts +14 -0
- package/ui.navigation-tabs/UTabs.vue +158 -6
- package/ui.navigation-tabs/config.ts +2 -1
- package/ui.navigation-tabs/constants.ts +2 -0
- package/ui.navigation-tabs/storybook/stories.ts +12 -1
- package/ui.navigation-tabs/tests/UTabs.test-d.ts +50 -0
- package/ui.navigation-tabs/tests/UTabs.test.ts +213 -1
- package/ui.navigation-tabs/tests/UTabsTypes.vue +65 -0
- package/ui.navigation-tabs/types.ts +26 -4
- package/ui.skeleton-text/constants.ts +1 -1
- package/ui.text-badge/config.ts +1 -1
- package/utils/node/loaderIcon.js +1 -1
- package/v.tooltip/vTooltip.ts +1 -1
package/README.md
CHANGED
|
@@ -14,7 +14,7 @@ A UI library with Open Architecture for Vue.js 3 and Nuxt.js 3 / 4, powered by [
|
|
|
14
14
|
|
|
15
15
|
### Key features
|
|
16
16
|
|
|
17
|
-
- 🧩
|
|
17
|
+
- 🧩 74 crafted UI components (including range date picker, multi-select, and nested table)
|
|
18
18
|
- ✨ Open Architecture lets you customize, copy, extend, and create your own components
|
|
19
19
|
- 📕 Built-in Storybook support
|
|
20
20
|
- 🪩 Theme Builder for runtime theme customization
|
package/composables/useUI.ts
CHANGED
|
@@ -228,6 +228,16 @@ export function useUI<T>(defaultConfig: T, mutatedProps?: MutatedProps, topLevel
|
|
|
228
228
|
const keysAttrs: KeysAttrs<T> = {};
|
|
229
229
|
const attrsRefs: Record<string, Ref<KeyAttrs>> = {};
|
|
230
230
|
|
|
231
|
+
/**
|
|
232
|
+
* Structural signature per key. The watcher below fires on any config/prop/class
|
|
233
|
+
* change and would otherwise re-mint every key's attrs object — even keys whose
|
|
234
|
+
* classes are identical — invalidating downstream reactive readers (e.g. every
|
|
235
|
+
* body row of a table on an unrelated sticky toggle). We skip the `.value` write
|
|
236
|
+
* when the new object is structurally equal to the last one, so the ref keeps its
|
|
237
|
+
* identity and dependents are not re-rendered.
|
|
238
|
+
*/
|
|
239
|
+
const attrsSignatures: Record<string, string> = {};
|
|
240
|
+
|
|
231
241
|
for (const key in config.value) {
|
|
232
242
|
if (isSystemKey(key)) continue;
|
|
233
243
|
|
|
@@ -266,12 +276,20 @@ export function useUI<T>(defaultConfig: T, mutatedProps?: MutatedProps, topLevel
|
|
|
266
276
|
/* Delete value key to prevent v-model overwrite. */
|
|
267
277
|
delete commonAttrs.value;
|
|
268
278
|
|
|
269
|
-
|
|
279
|
+
const nextValue: KeyAttrs = {
|
|
270
280
|
...commonAttrs,
|
|
271
281
|
class: cx([...data.extendsClasses, classes, commonAttrs.class]),
|
|
272
282
|
config: data.mergedNestedConfig,
|
|
273
283
|
...data.mergedDefaults,
|
|
274
284
|
};
|
|
285
|
+
|
|
286
|
+
/* Keep the previous ref identity when nothing changed — see attrsSignatures. */
|
|
287
|
+
const signature = JSON.stringify(nextValue);
|
|
288
|
+
|
|
289
|
+
if (attrsSignatures[key] === signature) continue;
|
|
290
|
+
|
|
291
|
+
attrsSignatures[key] = signature;
|
|
292
|
+
attrsRefs[key].value = nextValue;
|
|
275
293
|
}
|
|
276
294
|
},
|
|
277
295
|
{ immediate: true },
|
package/index.d.ts
CHANGED
|
@@ -108,6 +108,134 @@ export type {
|
|
|
108
108
|
LocaleInstance,
|
|
109
109
|
LocaleMessages,
|
|
110
110
|
} from "./types";
|
|
111
|
+
/* component props */
|
|
112
|
+
export type { Props as UAccordionProps } from "./ui.container-accordion/types";
|
|
113
|
+
export type { Props as UAccordionItemProps } from "./ui.container-accordion-item/types";
|
|
114
|
+
export type { Props as UAlertProps } from "./ui.text-alert/types";
|
|
115
|
+
export type { Props as UAvatarProps } from "./ui.image-avatar/types";
|
|
116
|
+
export type { Props as UAvatarGroupProps } from "./ui.image-avatar-group/types";
|
|
117
|
+
export type { Props as UBadgeProps } from "./ui.text-badge/types";
|
|
118
|
+
export type { Props as UBoilerplateProps } from "./ui.boilerplate/types";
|
|
119
|
+
export type { Props as UBreadcrumbsProps } from "./ui.navigation-breadcrumbs/types";
|
|
120
|
+
export type { Props as UButtonProps } from "./ui.button/types";
|
|
121
|
+
export type { Props as UCalendarProps } from "./ui.form-calendar/types";
|
|
122
|
+
export type { Props as UCardProps } from "./ui.container-card/types";
|
|
123
|
+
export type { Props as UCheckboxProps } from "./ui.form-checkbox/types";
|
|
124
|
+
export type { Props as UCheckboxGroupProps } from "./ui.form-checkbox-group/types";
|
|
125
|
+
export type { Props as UCheckboxMultiStateProps } from "./ui.form-checkbox-multi-state/types";
|
|
126
|
+
export type { Props as UChipProps } from "./ui.other-chip/types";
|
|
127
|
+
export type { Props as UColProps } from "./ui.container-col/types";
|
|
128
|
+
export type { Props as UCollapsibleProps } from "./ui.container-collapsible/types";
|
|
129
|
+
export type { Props as UColorToggleProps } from "./ui.form-color-toggle/types";
|
|
130
|
+
export type { Props as UDataListProps } from "./ui.data-list/types";
|
|
131
|
+
export type { Props as UDatePickerProps } from "./ui.form-date-picker/types";
|
|
132
|
+
export type { Props as UDatePickerRangeProps } from "./ui.form-date-picker-range/types";
|
|
133
|
+
export type { Props as UDividerProps } from "./ui.container-divider/types";
|
|
134
|
+
export type { Props as UDotProps } from "./ui.other-dot/types";
|
|
135
|
+
export type { Props as UDrawerProps } from "./ui.container-drawer/types";
|
|
136
|
+
export type { Props as UDropdownProps } from "./ui.dropdown/types";
|
|
137
|
+
export type { Props as UDropdownBadgeProps } from "./ui.dropdown-badge/types";
|
|
138
|
+
export type { Props as UDropdownButtonProps } from "./ui.dropdown-button/types";
|
|
139
|
+
export type { Props as UDropdownLinkProps } from "./ui.dropdown-link/types";
|
|
140
|
+
export type { Props as UEmptyProps } from "./ui.container-empty/types";
|
|
141
|
+
export type { Props as UFileProps } from "./ui.text-file/types";
|
|
142
|
+
export type { Props as UFilesProps } from "./ui.text-files/types";
|
|
143
|
+
export type { Props as UGridProps } from "./ui.container-grid/types";
|
|
144
|
+
export type { Props as UGroupProps } from "./ui.container-group/types";
|
|
145
|
+
export type { Props as UGroupsProps } from "./ui.container-groups/types";
|
|
146
|
+
export type { Props as UHeaderProps } from "./ui.text-header/types";
|
|
147
|
+
export type { Props as UIconProps } from "./ui.image-icon/types";
|
|
148
|
+
export type { Props as UInputProps } from "./ui.form-input/types";
|
|
149
|
+
export type { Props as UInputCounterProps } from "./ui.form-input-counter/types";
|
|
150
|
+
export type { Props as UInputFileProps } from "./ui.form-input-file/types";
|
|
151
|
+
export type { Props as UInputNumberProps } from "./ui.form-input-number/types";
|
|
152
|
+
export type { Props as UInputPasswordProps } from "./ui.form-input-password/types";
|
|
153
|
+
export type { Props as UInputRatingProps } from "./ui.form-input-rating/types";
|
|
154
|
+
export type { Props as UInputSearchProps } from "./ui.form-input-search/types";
|
|
155
|
+
export type { Props as UKeyProps } from "./ui.text-key/types";
|
|
156
|
+
export type { Props as ULabelProps } from "./ui.form-label/types";
|
|
157
|
+
export type { Props as ULinkProps } from "./ui.button-link/types";
|
|
158
|
+
export type { Props as UListboxProps } from "./ui.form-listbox/types";
|
|
159
|
+
export type { Props as ULoaderProps } from "./ui.loader/types";
|
|
160
|
+
export type { Props as ULoaderOverlayProps } from "./ui.loader-overlay/types";
|
|
161
|
+
export type { Props as ULoaderProgressProps } from "./ui.loader-progress/types";
|
|
162
|
+
export type { Props as UModalProps } from "./ui.container-modal/types";
|
|
163
|
+
export type { Props as UModalConfirmProps } from "./ui.container-modal-confirm/types";
|
|
164
|
+
export type { Props as UNotifyProps } from "./ui.text-notify/types";
|
|
165
|
+
export type { Props as UNumberProps } from "./ui.text-number/types";
|
|
166
|
+
export type { Props as UPageProps } from "./ui.container-page/types";
|
|
167
|
+
export type { Props as UPaginationProps } from "./ui.navigation-pagination/types";
|
|
168
|
+
export type { Props as UPlaceholderProps } from "./ui.container-placeholder/types";
|
|
169
|
+
export type { Props as UProgressProps } from "./ui.navigation-progress/types";
|
|
170
|
+
export type { Props as URadioProps } from "./ui.form-radio/types";
|
|
171
|
+
export type { Props as URadioGroupProps } from "./ui.form-radio-group/types";
|
|
172
|
+
export type { Props as URowProps } from "./ui.container-row/types";
|
|
173
|
+
export type { Props as USelectProps } from "./ui.form-select/types";
|
|
174
|
+
export type { Props as USkeletonProps } from "./ui.skeleton/types";
|
|
175
|
+
export type { Props as USkeletonChoiceProps } from "./ui.skeleton-choice/types";
|
|
176
|
+
export type { Props as USkeletonInputProps } from "./ui.skeleton-input/types";
|
|
177
|
+
export type { Props as USkeletonTextProps } from "./ui.skeleton-text/types";
|
|
178
|
+
export type { Props as USplitterProps } from "./ui.container-splitter/types";
|
|
179
|
+
export type { Props as USwitchProps } from "./ui.form-switch/types";
|
|
180
|
+
export type { Props as UTabProps } from "./ui.navigation-tab/types";
|
|
181
|
+
export type { Props as UTableProps } from "./ui.data-table/types";
|
|
182
|
+
export type { Props as UTabsProps } from "./ui.navigation-tabs/types";
|
|
183
|
+
export type { Props as UTextProps } from "./ui.text-block/types";
|
|
184
|
+
export type { Props as UTextareaProps } from "./ui.form-textarea/types";
|
|
185
|
+
export type { Props as UThemeColorToggleProps } from "./ui.other-theme-color-toggle/types";
|
|
186
|
+
export type { Props as UToggleProps } from "./ui.button-toggle/types";
|
|
187
|
+
/* component data types */
|
|
188
|
+
export type {
|
|
189
|
+
Row,
|
|
190
|
+
BaseRow,
|
|
191
|
+
TableRow,
|
|
192
|
+
FlatRow,
|
|
193
|
+
RowId,
|
|
194
|
+
RowData,
|
|
195
|
+
Cell,
|
|
196
|
+
CellObject,
|
|
197
|
+
Column,
|
|
198
|
+
ColumnObject,
|
|
199
|
+
TableColumn,
|
|
200
|
+
DateDivider,
|
|
201
|
+
BaseDateDivider,
|
|
202
|
+
SlotRow,
|
|
203
|
+
SelectedSlotRow,
|
|
204
|
+
UTableSlots,
|
|
205
|
+
UTableStaticSlots,
|
|
206
|
+
UTableDynamicSlots,
|
|
207
|
+
} from "./ui.data-table/types";
|
|
208
|
+
export type {
|
|
209
|
+
Option,
|
|
210
|
+
BaseOption,
|
|
211
|
+
ListboxOption,
|
|
212
|
+
SelectedValue,
|
|
213
|
+
SlotOption,
|
|
214
|
+
UListboxSlots,
|
|
215
|
+
} from "./ui.form-listbox/types";
|
|
216
|
+
export type {
|
|
217
|
+
SelectOption,
|
|
218
|
+
SelectedSlotOption,
|
|
219
|
+
SelectedOptionsBinding,
|
|
220
|
+
USelectSlots,
|
|
221
|
+
} from "./ui.form-select/types";
|
|
222
|
+
export type { UDropdownSlots } from "./ui.dropdown/types";
|
|
223
|
+
export type { UDropdownBadgeSlots } from "./ui.dropdown-badge/types";
|
|
224
|
+
export type { UDropdownButtonSlots } from "./ui.dropdown-button/types";
|
|
225
|
+
export type { UDropdownLinkSlots } from "./ui.dropdown-link/types";
|
|
226
|
+
export type { UTabsOption, BaseTabOption, UTabsSlots } from "./ui.navigation-tabs/types";
|
|
227
|
+
export type { UBreadcrumb, BaseBreadcrumb } from "./ui.navigation-breadcrumbs/types";
|
|
228
|
+
export type { UToggleOption, BaseToggleOption, UToggleSlots } from "./ui.button-toggle/types";
|
|
229
|
+
export type { UAccordionOption, BaseAccordionOption } from "./ui.container-accordion/types";
|
|
230
|
+
export type {
|
|
231
|
+
DataListItem,
|
|
232
|
+
BaseDataListItem,
|
|
233
|
+
SlotItem,
|
|
234
|
+
UDataListSlots,
|
|
235
|
+
} from "./ui.data-list/types";
|
|
236
|
+
export type { UCheckboxOption, BaseCheckboxOption } from "./ui.form-checkbox/types";
|
|
237
|
+
export type { ChipItem, BaseChipItem } from "./ui.image-avatar/types";
|
|
238
|
+
export type { AvatarItem, BaseAvatarItem } from "./ui.image-avatar-group/types";
|
|
111
239
|
/* Export enums directly (not as types) */
|
|
112
240
|
export { ColorMode } from "./types";
|
|
113
241
|
|
package/index.ts
CHANGED
|
@@ -114,6 +114,134 @@ export type {
|
|
|
114
114
|
LocaleInstance,
|
|
115
115
|
LocaleMessages,
|
|
116
116
|
} from "./types";
|
|
117
|
+
/* component props */
|
|
118
|
+
export type { Props as UAccordionProps } from "./ui.container-accordion/types";
|
|
119
|
+
export type { Props as UAccordionItemProps } from "./ui.container-accordion-item/types";
|
|
120
|
+
export type { Props as UAlertProps } from "./ui.text-alert/types";
|
|
121
|
+
export type { Props as UAvatarProps } from "./ui.image-avatar/types";
|
|
122
|
+
export type { Props as UAvatarGroupProps } from "./ui.image-avatar-group/types";
|
|
123
|
+
export type { Props as UBadgeProps } from "./ui.text-badge/types";
|
|
124
|
+
export type { Props as UBoilerplateProps } from "./ui.boilerplate/types";
|
|
125
|
+
export type { Props as UBreadcrumbsProps } from "./ui.navigation-breadcrumbs/types";
|
|
126
|
+
export type { Props as UButtonProps } from "./ui.button/types";
|
|
127
|
+
export type { Props as UCalendarProps } from "./ui.form-calendar/types";
|
|
128
|
+
export type { Props as UCardProps } from "./ui.container-card/types";
|
|
129
|
+
export type { Props as UCheckboxProps } from "./ui.form-checkbox/types";
|
|
130
|
+
export type { Props as UCheckboxGroupProps } from "./ui.form-checkbox-group/types";
|
|
131
|
+
export type { Props as UCheckboxMultiStateProps } from "./ui.form-checkbox-multi-state/types";
|
|
132
|
+
export type { Props as UChipProps } from "./ui.other-chip/types";
|
|
133
|
+
export type { Props as UColProps } from "./ui.container-col/types";
|
|
134
|
+
export type { Props as UCollapsibleProps } from "./ui.container-collapsible/types";
|
|
135
|
+
export type { Props as UColorToggleProps } from "./ui.form-color-toggle/types";
|
|
136
|
+
export type { Props as UDataListProps } from "./ui.data-list/types";
|
|
137
|
+
export type { Props as UDatePickerProps } from "./ui.form-date-picker/types";
|
|
138
|
+
export type { Props as UDatePickerRangeProps } from "./ui.form-date-picker-range/types";
|
|
139
|
+
export type { Props as UDividerProps } from "./ui.container-divider/types";
|
|
140
|
+
export type { Props as UDotProps } from "./ui.other-dot/types";
|
|
141
|
+
export type { Props as UDrawerProps } from "./ui.container-drawer/types";
|
|
142
|
+
export type { Props as UDropdownProps } from "./ui.dropdown/types";
|
|
143
|
+
export type { Props as UDropdownBadgeProps } from "./ui.dropdown-badge/types";
|
|
144
|
+
export type { Props as UDropdownButtonProps } from "./ui.dropdown-button/types";
|
|
145
|
+
export type { Props as UDropdownLinkProps } from "./ui.dropdown-link/types";
|
|
146
|
+
export type { Props as UEmptyProps } from "./ui.container-empty/types";
|
|
147
|
+
export type { Props as UFileProps } from "./ui.text-file/types";
|
|
148
|
+
export type { Props as UFilesProps } from "./ui.text-files/types";
|
|
149
|
+
export type { Props as UGridProps } from "./ui.container-grid/types";
|
|
150
|
+
export type { Props as UGroupProps } from "./ui.container-group/types";
|
|
151
|
+
export type { Props as UGroupsProps } from "./ui.container-groups/types";
|
|
152
|
+
export type { Props as UHeaderProps } from "./ui.text-header/types";
|
|
153
|
+
export type { Props as UIconProps } from "./ui.image-icon/types";
|
|
154
|
+
export type { Props as UInputProps } from "./ui.form-input/types";
|
|
155
|
+
export type { Props as UInputCounterProps } from "./ui.form-input-counter/types";
|
|
156
|
+
export type { Props as UInputFileProps } from "./ui.form-input-file/types";
|
|
157
|
+
export type { Props as UInputNumberProps } from "./ui.form-input-number/types";
|
|
158
|
+
export type { Props as UInputPasswordProps } from "./ui.form-input-password/types";
|
|
159
|
+
export type { Props as UInputRatingProps } from "./ui.form-input-rating/types";
|
|
160
|
+
export type { Props as UInputSearchProps } from "./ui.form-input-search/types";
|
|
161
|
+
export type { Props as UKeyProps } from "./ui.text-key/types";
|
|
162
|
+
export type { Props as ULabelProps } from "./ui.form-label/types";
|
|
163
|
+
export type { Props as ULinkProps } from "./ui.button-link/types";
|
|
164
|
+
export type { Props as UListboxProps } from "./ui.form-listbox/types";
|
|
165
|
+
export type { Props as ULoaderProps } from "./ui.loader/types";
|
|
166
|
+
export type { Props as ULoaderOverlayProps } from "./ui.loader-overlay/types";
|
|
167
|
+
export type { Props as ULoaderProgressProps } from "./ui.loader-progress/types";
|
|
168
|
+
export type { Props as UModalProps } from "./ui.container-modal/types";
|
|
169
|
+
export type { Props as UModalConfirmProps } from "./ui.container-modal-confirm/types";
|
|
170
|
+
export type { Props as UNotifyProps } from "./ui.text-notify/types";
|
|
171
|
+
export type { Props as UNumberProps } from "./ui.text-number/types";
|
|
172
|
+
export type { Props as UPageProps } from "./ui.container-page/types";
|
|
173
|
+
export type { Props as UPaginationProps } from "./ui.navigation-pagination/types";
|
|
174
|
+
export type { Props as UPlaceholderProps } from "./ui.container-placeholder/types";
|
|
175
|
+
export type { Props as UProgressProps } from "./ui.navigation-progress/types";
|
|
176
|
+
export type { Props as URadioProps } from "./ui.form-radio/types";
|
|
177
|
+
export type { Props as URadioGroupProps } from "./ui.form-radio-group/types";
|
|
178
|
+
export type { Props as URowProps } from "./ui.container-row/types";
|
|
179
|
+
export type { Props as USelectProps } from "./ui.form-select/types";
|
|
180
|
+
export type { Props as USkeletonProps } from "./ui.skeleton/types";
|
|
181
|
+
export type { Props as USkeletonChoiceProps } from "./ui.skeleton-choice/types";
|
|
182
|
+
export type { Props as USkeletonInputProps } from "./ui.skeleton-input/types";
|
|
183
|
+
export type { Props as USkeletonTextProps } from "./ui.skeleton-text/types";
|
|
184
|
+
export type { Props as USplitterProps } from "./ui.container-splitter/types";
|
|
185
|
+
export type { Props as USwitchProps } from "./ui.form-switch/types";
|
|
186
|
+
export type { Props as UTabProps } from "./ui.navigation-tab/types";
|
|
187
|
+
export type { Props as UTableProps } from "./ui.data-table/types";
|
|
188
|
+
export type { Props as UTabsProps } from "./ui.navigation-tabs/types";
|
|
189
|
+
export type { Props as UTextProps } from "./ui.text-block/types";
|
|
190
|
+
export type { Props as UTextareaProps } from "./ui.form-textarea/types";
|
|
191
|
+
export type { Props as UThemeColorToggleProps } from "./ui.other-theme-color-toggle/types";
|
|
192
|
+
export type { Props as UToggleProps } from "./ui.button-toggle/types";
|
|
193
|
+
/* component data types */
|
|
194
|
+
export type {
|
|
195
|
+
Row,
|
|
196
|
+
BaseRow,
|
|
197
|
+
TableRow,
|
|
198
|
+
FlatRow,
|
|
199
|
+
RowId,
|
|
200
|
+
RowData,
|
|
201
|
+
Cell,
|
|
202
|
+
CellObject,
|
|
203
|
+
Column,
|
|
204
|
+
ColumnObject,
|
|
205
|
+
TableColumn,
|
|
206
|
+
DateDivider,
|
|
207
|
+
BaseDateDivider,
|
|
208
|
+
SlotRow,
|
|
209
|
+
SelectedSlotRow,
|
|
210
|
+
UTableSlots,
|
|
211
|
+
UTableStaticSlots,
|
|
212
|
+
UTableDynamicSlots,
|
|
213
|
+
} from "./ui.data-table/types";
|
|
214
|
+
export type {
|
|
215
|
+
Option,
|
|
216
|
+
BaseOption,
|
|
217
|
+
ListboxOption,
|
|
218
|
+
SelectedValue,
|
|
219
|
+
SlotOption,
|
|
220
|
+
UListboxSlots,
|
|
221
|
+
} from "./ui.form-listbox/types";
|
|
222
|
+
export type {
|
|
223
|
+
SelectOption,
|
|
224
|
+
SelectedSlotOption,
|
|
225
|
+
SelectedOptionsBinding,
|
|
226
|
+
USelectSlots,
|
|
227
|
+
} from "./ui.form-select/types";
|
|
228
|
+
export type { UDropdownSlots } from "./ui.dropdown/types";
|
|
229
|
+
export type { UDropdownBadgeSlots } from "./ui.dropdown-badge/types";
|
|
230
|
+
export type { UDropdownButtonSlots } from "./ui.dropdown-button/types";
|
|
231
|
+
export type { UDropdownLinkSlots } from "./ui.dropdown-link/types";
|
|
232
|
+
export type { UTabsOption, BaseTabOption, UTabsSlots } from "./ui.navigation-tabs/types";
|
|
233
|
+
export type { UBreadcrumb, BaseBreadcrumb } from "./ui.navigation-breadcrumbs/types";
|
|
234
|
+
export type { UToggleOption, BaseToggleOption, UToggleSlots } from "./ui.button-toggle/types";
|
|
235
|
+
export type { UAccordionOption, BaseAccordionOption } from "./ui.container-accordion/types";
|
|
236
|
+
export type {
|
|
237
|
+
DataListItem,
|
|
238
|
+
BaseDataListItem,
|
|
239
|
+
SlotItem,
|
|
240
|
+
UDataListSlots,
|
|
241
|
+
} from "./ui.data-list/types";
|
|
242
|
+
export type { UCheckboxOption, BaseCheckboxOption } from "./ui.form-checkbox/types";
|
|
243
|
+
export type { ChipItem, BaseChipItem } from "./ui.image-avatar/types";
|
|
244
|
+
export type { AvatarItem, BaseAvatarItem } from "./ui.image-avatar-group/types";
|
|
117
245
|
/* Export enums directly (not as types) */
|
|
118
246
|
export { ColorMode } from "./types";
|
|
119
247
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vueless",
|
|
3
|
-
"version": "1.4.12-beta.
|
|
3
|
+
"version": "1.4.12-beta.21",
|
|
4
4
|
"description": "Vue Styleless UI Component Library, powered by Tailwind CSS.",
|
|
5
5
|
"author": "Johnny Grid <hello@vueless.com> (https://vueless.com)",
|
|
6
6
|
"homepage": "https://vueless.com",
|
|
@@ -48,8 +48,8 @@
|
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
50
|
"@material-symbols/svg-500": "^0.44.4",
|
|
51
|
-
"@release-it/bumper": "^
|
|
52
|
-
"@release-it/conventional-changelog": "^
|
|
51
|
+
"@release-it/bumper": "^8.0.1",
|
|
52
|
+
"@release-it/conventional-changelog": "^12.0.2",
|
|
53
53
|
"@tsconfig/node24": "^24.0.0",
|
|
54
54
|
"@types/jsdom": "^28.0.1",
|
|
55
55
|
"@types/node": "24.1.0",
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
"@vue/eslint-config-typescript": "^14.7.0",
|
|
60
60
|
"@vue/test-utils": "^2.4.8",
|
|
61
61
|
"@vue/tsconfig": "^0.9.1",
|
|
62
|
-
"@vueless/storybook": "^1.
|
|
62
|
+
"@vueless/storybook": "^1.8.0",
|
|
63
63
|
"eslint": "^10.2.1",
|
|
64
64
|
"eslint-plugin-storybook": "^10.3.5",
|
|
65
65
|
"eslint-plugin-tailwindcss": "^4.0.0-alpha.7",
|
|
@@ -67,7 +67,7 @@
|
|
|
67
67
|
"globals": "^17.5.0",
|
|
68
68
|
"jsdom": "^29.0.2",
|
|
69
69
|
"prettier": "^3.8.3",
|
|
70
|
-
"release-it": "^
|
|
70
|
+
"release-it": "^21.0.3",
|
|
71
71
|
"typescript": "^6.0.3",
|
|
72
72
|
"vite": "^8.0.10",
|
|
73
73
|
"vitest": "^4.1.5",
|
|
@@ -105,9 +105,6 @@
|
|
|
105
105
|
"types": "./modules.d.ts"
|
|
106
106
|
}
|
|
107
107
|
},
|
|
108
|
-
"overrides": {
|
|
109
|
-
"conventional-changelog-conventionalcommits": "8.0.0"
|
|
110
|
-
},
|
|
111
108
|
"resolutions": {
|
|
112
109
|
"jackspeak": "2.3.6"
|
|
113
110
|
},
|
|
@@ -136,5 +133,9 @@
|
|
|
136
133
|
"styleless",
|
|
137
134
|
"headlessui",
|
|
138
135
|
"ui"
|
|
139
|
-
]
|
|
136
|
+
],
|
|
137
|
+
"allowScripts": {
|
|
138
|
+
"esbuild@0.28.1": true,
|
|
139
|
+
"fsevents@2.3.3": true
|
|
140
|
+
}
|
|
140
141
|
}
|
package/ui.button/config.ts
CHANGED
|
@@ -2,7 +2,7 @@ export default /*tw*/ {
|
|
|
2
2
|
button: {
|
|
3
3
|
base: `
|
|
4
4
|
flex items-center justify-center font-medium leading-snug! whitespace-nowrap
|
|
5
|
-
border border-solid outline-solid outline-transparent transition cursor-pointer
|
|
5
|
+
border border-solid outline-solid outline-medium outline-transparent transition cursor-pointer
|
|
6
6
|
focus-visible:outline-medium focus-visible:outline-offset-2 focus-visible:outline-{color}
|
|
7
7
|
disabled:cursor-not-allowed disabled:outline-0 disabled:outline-offset-0
|
|
8
8
|
`,
|
package/ui.button-link/config.ts
CHANGED
|
@@ -5,7 +5,7 @@ export default /*tw*/ {
|
|
|
5
5
|
text-{color} decoration-{color} underline-offset-4
|
|
6
6
|
hover:text-{color}-lifted hover:decoration-{color}-lifted
|
|
7
7
|
active:text-{color}-accented active:decoration-{color}-accented
|
|
8
|
-
outline-solid outline-transparent
|
|
8
|
+
outline-solid outline-medium outline-transparent
|
|
9
9
|
focus-visible:outline-medium focus-visible:rounded-small
|
|
10
10
|
focus-visible:outline-offset-4 focus-visible:outline-{color}
|
|
11
11
|
`,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
1
|
+
<script setup lang="ts" generic="TItem extends UToggleOption">
|
|
2
2
|
import { computed, ref, useId, useTemplateRef } from "vue";
|
|
3
3
|
|
|
4
4
|
import UButton from "../ui.button/UButton.vue";
|
|
@@ -9,16 +9,18 @@ import { getDefaults } from "../utils/ui";
|
|
|
9
9
|
import defaultConfig from "./config";
|
|
10
10
|
import { COMPONENT_NAME } from "./constants";
|
|
11
11
|
|
|
12
|
-
import type { Props, Config, UToggleOption } from "./types";
|
|
12
|
+
import type { Props, Config, UToggleOption, UToggleSlots } from "./types";
|
|
13
13
|
|
|
14
14
|
defineOptions({ inheritAttrs: false });
|
|
15
15
|
|
|
16
|
-
const props = withDefaults(defineProps<Props
|
|
17
|
-
...getDefaults<Props
|
|
16
|
+
const props = withDefaults(defineProps<Props<TItem>>(), {
|
|
17
|
+
...getDefaults<Props<TItem>, Config>(defaultConfig, COMPONENT_NAME),
|
|
18
18
|
options: () => [],
|
|
19
19
|
modelValue: () => [],
|
|
20
20
|
});
|
|
21
21
|
|
|
22
|
+
defineSlots<UToggleSlots<TItem>>();
|
|
23
|
+
|
|
22
24
|
const emit = defineEmits([
|
|
23
25
|
/**
|
|
24
26
|
* Triggers when toggle option is selected.
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
getDocsDescription,
|
|
8
8
|
} from "../../utils/storybook";
|
|
9
9
|
|
|
10
|
-
import
|
|
10
|
+
import UToggleComponent from "../../ui.button-toggle/UToggle.vue";
|
|
11
11
|
import UIcon from "../../ui.image-icon/UIcon.vue";
|
|
12
12
|
import URow from "../../ui.container-row/URow.vue";
|
|
13
13
|
import UBadge from "../../ui.text-badge/UBadge.vue";
|
|
@@ -17,6 +17,9 @@ import ULabel from "../../ui.form-label/ULabel.vue";
|
|
|
17
17
|
import type { Meta, StoryFn } from "@storybook/vue3-vite";
|
|
18
18
|
import type { Props } from "../types";
|
|
19
19
|
|
|
20
|
+
/* Generic SFCs are typed as a function, which drops the compiler-generated `__name`. */
|
|
21
|
+
const UToggle = UToggleComponent as typeof UToggleComponent & { __name: string };
|
|
22
|
+
|
|
20
23
|
interface UToggleArgs extends Props {
|
|
21
24
|
slotTemplate?: string;
|
|
22
25
|
enum: "size";
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { describe, it, expectTypeOf } from "vitest";
|
|
2
|
+
|
|
3
|
+
import type { Props, UToggleOption, UToggleSlots } from "../types";
|
|
4
|
+
|
|
5
|
+
interface CountedOption {
|
|
6
|
+
value: string;
|
|
7
|
+
label: string;
|
|
8
|
+
count: number;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
type OptionProps = Parameters<NonNullable<UToggleSlots<CountedOption>["option"]>>[0];
|
|
12
|
+
|
|
13
|
+
describe("UToggle types", () => {
|
|
14
|
+
it("infers the caller's option shape in a slot", () => {
|
|
15
|
+
expectTypeOf<OptionProps["option"]>().toEqualTypeOf<CountedOption>();
|
|
16
|
+
expectTypeOf<OptionProps["option"]["count"]>().toEqualTypeOf<number>();
|
|
17
|
+
expectTypeOf<OptionProps["index"]>().toEqualTypeOf<number>();
|
|
18
|
+
expectTypeOf<OptionProps["label"]>().toEqualTypeOf<string>();
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it("promises the caller's members — options reach slots untransformed", () => {
|
|
22
|
+
/* Unlike UTable, `UToggle` iterates `props.options` directly: no flattening, filtering
|
|
23
|
+
* or synthetic entries, so the members are guaranteed rather than optional. */
|
|
24
|
+
expectTypeOf<OptionProps["option"]["label"]>().toEqualTypeOf<string>();
|
|
25
|
+
expectTypeOf<undefined>().not.toExtend<OptionProps["option"]["count"]>();
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it("does not expose undeclared option properties to a slot", () => {
|
|
29
|
+
type HasIndexSignature = string extends keyof OptionProps["option"] ? true : false;
|
|
30
|
+
|
|
31
|
+
expectTypeOf<HasIndexSignature>().toEqualTypeOf<false>();
|
|
32
|
+
expectTypeOf<keyof OptionProps["option"]>().not.toEqualTypeOf<string>();
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it("types the remaining slots", () => {
|
|
36
|
+
type Left = Parameters<NonNullable<UToggleSlots<CountedOption>["left"]>>[0];
|
|
37
|
+
type Right = Parameters<NonNullable<UToggleSlots<CountedOption>["right"]>>[0];
|
|
38
|
+
|
|
39
|
+
expectTypeOf<Left["option"]>().toEqualTypeOf<CountedOption>();
|
|
40
|
+
expectTypeOf<Right["option"]>().toEqualTypeOf<CountedOption>();
|
|
41
|
+
expectTypeOf<Left["iconName"]>().toEqualTypeOf<string | undefined>();
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it("resolves Props with no type argument", () => {
|
|
45
|
+
expectTypeOf<Props>().toEqualTypeOf<Props<UToggleOption>>();
|
|
46
|
+
expectTypeOf<Props<CountedOption>["options"]>().toEqualTypeOf<CountedOption[] | undefined>();
|
|
47
|
+
});
|
|
48
|
+
});
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
<!-- Type-level fixture: checked by `npm run ts:check`, never mounted.
|
|
2
|
+
Proves slot props infer from the `options` prop at a real call site. -->
|
|
3
|
+
<template>
|
|
4
|
+
<!-- `UToggle` iterates `options` verbatim, so the caller's shape is guaranteed, not optional. -->
|
|
5
|
+
<UToggle name="fixture" :options="options">
|
|
6
|
+
<template #left="{ option, index, iconName }">
|
|
7
|
+
{{ expectString(option.color) }}
|
|
8
|
+
{{ expectNumber(index) }}
|
|
9
|
+
{{ expectOptionalString(iconName) }}
|
|
10
|
+
</template>
|
|
11
|
+
|
|
12
|
+
<template #option="{ option, label, index }">
|
|
13
|
+
{{ expectString(option.color) }}
|
|
14
|
+
{{ expectString(label) }}
|
|
15
|
+
{{ expectNumber(index) }}
|
|
16
|
+
</template>
|
|
17
|
+
|
|
18
|
+
<template #right="{ option }">
|
|
19
|
+
<!-- @vue-expect-error `nonExistent` is not a key of the inferred option. -->
|
|
20
|
+
{{ option.nonExistent }}
|
|
21
|
+
</template>
|
|
22
|
+
</UToggle>
|
|
23
|
+
|
|
24
|
+
<!-- Options from a non-literal source still expose the declared option shape. -->
|
|
25
|
+
<UToggle name="typed" :options="typedOptions">
|
|
26
|
+
<template #option="{ option }">{{ expectNumber(option.count) }}</template>
|
|
27
|
+
</UToggle>
|
|
28
|
+
</template>
|
|
29
|
+
|
|
30
|
+
<script setup lang="ts">
|
|
31
|
+
import { ref } from "vue";
|
|
32
|
+
|
|
33
|
+
import UToggle from "../UToggle.vue";
|
|
34
|
+
|
|
35
|
+
interface CountedOption {
|
|
36
|
+
value: string;
|
|
37
|
+
label: string;
|
|
38
|
+
count: number;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const options = [{ value: "1", label: "Success", color: "success" }];
|
|
42
|
+
const typedOptions = ref<CountedOption[]>([]);
|
|
43
|
+
|
|
44
|
+
function expectString(value: string) {
|
|
45
|
+
return value;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function expectNumber(value: number) {
|
|
49
|
+
return value;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function expectOptionalString(value: string | undefined) {
|
|
53
|
+
return value;
|
|
54
|
+
}
|
|
55
|
+
</script>
|
|
@@ -1,21 +1,33 @@
|
|
|
1
1
|
import defaultConfig from "./config";
|
|
2
2
|
|
|
3
|
-
import type { ComponentConfig } from "../types";
|
|
3
|
+
import type { ComponentConfig, UnknownObject } from "../types";
|
|
4
4
|
|
|
5
5
|
export type Config = typeof defaultConfig;
|
|
6
6
|
|
|
7
|
-
export interface
|
|
7
|
+
export interface BaseToggleOption {
|
|
8
8
|
value: string | number | boolean;
|
|
9
9
|
label?: string;
|
|
10
10
|
disabled?: boolean;
|
|
11
11
|
icon?: string;
|
|
12
12
|
leftIcon?: string;
|
|
13
13
|
rightIcon?: string;
|
|
14
|
-
onClick?: (option: Omit<
|
|
15
|
-
[key: string]: unknown;
|
|
14
|
+
onClick?: (option: Omit<BaseToggleOption, "onClick">) => void;
|
|
16
15
|
}
|
|
17
16
|
|
|
18
|
-
|
|
17
|
+
/* Any object shape is a valid option, only reserved option keys are type checked. */
|
|
18
|
+
export type UToggleOption = BaseToggleOption & (object | UnknownObject);
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Slots receive each option verbatim — `UToggle` iterates `props.options` without
|
|
22
|
+
* filtering, flattening or synthesising entries, so the caller's shape is guaranteed.
|
|
23
|
+
*/
|
|
24
|
+
export interface UToggleSlots<TItem extends UToggleOption = UToggleOption> {
|
|
25
|
+
left?: (props: { option: TItem; index: number; iconName?: string }) => unknown;
|
|
26
|
+
option?: (props: { option: TItem; index: number; label: string; iconName?: string }) => unknown;
|
|
27
|
+
right?: (props: { option: TItem; index: number; iconName?: string }) => unknown;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface Props<TItem extends UToggleOption = UToggleOption> {
|
|
19
31
|
/**
|
|
20
32
|
* Selected value.
|
|
21
33
|
*/
|
|
@@ -24,7 +36,7 @@ export interface Props {
|
|
|
24
36
|
/**
|
|
25
37
|
* Toggle item options.
|
|
26
38
|
*/
|
|
27
|
-
options?:
|
|
39
|
+
options?: TItem[];
|
|
28
40
|
|
|
29
41
|
/**
|
|
30
42
|
* Toggle size.
|
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
import defaultConfig from "./config";
|
|
2
|
-
import type { ComponentConfig } from "../types";
|
|
2
|
+
import type { ComponentConfig, UnknownObject } from "../types";
|
|
3
3
|
|
|
4
4
|
export type Config = typeof defaultConfig;
|
|
5
5
|
|
|
6
|
-
export interface
|
|
6
|
+
export interface BaseAccordionOption {
|
|
7
7
|
value: string;
|
|
8
8
|
title: string;
|
|
9
9
|
description?: string;
|
|
10
10
|
opened?: boolean;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
+
/* Any object shape is a valid option, only reserved option keys are type checked. */
|
|
14
|
+
export type UAccordionOption = BaseAccordionOption & (object | UnknownObject);
|
|
15
|
+
|
|
13
16
|
export type SetAccordionSelectedItem = (value: string, opened: boolean) => void;
|
|
14
17
|
|
|
15
18
|
export interface Props {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export default /*tw*/ {
|
|
2
2
|
wrapper: {
|
|
3
3
|
base: `
|
|
4
|
-
relative inline-block h-max rounded-medium transition cursor-pointer outline-solid outline-transparent
|
|
4
|
+
relative inline-block h-max rounded-medium transition cursor-pointer outline-solid outline-medium outline-transparent
|
|
5
5
|
focus-visible:outline-medium focus-visible:outline-offset-2 focus-visible:outline-primary`,
|
|
6
6
|
variants: {
|
|
7
7
|
disabled: {
|