@skewedaspect/sleekspace-ui 0.9.1 → 0.10.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.
- package/dist/components/Accordion/context.d.ts +4 -0
- package/dist/components/Autocomplete/SkAutocomplete.vue.d.ts +87 -0
- package/dist/components/Autocomplete/SkAutocompleteEmpty.vue.d.ts +17 -0
- package/dist/components/Autocomplete/SkAutocompleteGroup.vue.d.ts +17 -0
- package/dist/components/Autocomplete/SkAutocompleteGroupLabel.vue.d.ts +17 -0
- package/dist/components/Autocomplete/SkAutocompleteItem.vue.d.ts +39 -0
- package/dist/components/Autocomplete/SkAutocompleteSeparator.vue.d.ts +2 -0
- package/dist/components/Autocomplete/index.d.ts +7 -0
- package/dist/components/Autocomplete/types.d.ts +3 -0
- package/dist/components/Breadcrumbs/context.d.ts +4 -0
- package/dist/components/Button/SkButton.vue.d.ts +8 -1
- package/dist/components/Button/types.d.ts +2 -0
- package/dist/components/Card/SkCard.vue.d.ts +1 -1
- package/dist/components/ContextMenu/context.d.ts +3 -0
- package/dist/components/Dropdown/SkDropdown.vue.d.ts +1 -1
- package/dist/components/Dropdown/context.d.ts +3 -0
- package/dist/components/Field/SkField.vue.d.ts +7 -6
- package/dist/components/Input/SkInput.vue.d.ts +9 -2
- package/dist/components/Input/types.d.ts +2 -0
- package/dist/components/InputGroup/SkInputGroup.vue.d.ts +23 -0
- package/dist/components/InputGroup/SkInputGroupAddon.vue.d.ts +33 -0
- package/dist/components/InputGroup/types.d.ts +13 -0
- package/dist/components/NumberInput/SkNumberInput.vue.d.ts +7 -1
- package/dist/components/NumberInput/types.d.ts +2 -0
- package/dist/components/Pagination/context.d.ts +5 -0
- package/dist/components/Panel/SkPanel.vue.d.ts +1 -1
- package/dist/components/Panel/types.d.ts +2 -1
- package/dist/components/Radio/context.d.ts +4 -0
- package/dist/components/Select/SkSelect.vue.d.ts +7 -1
- package/dist/components/Select/types.d.ts +2 -0
- package/dist/components/Sidebar/SkSidebar.vue.d.ts +1 -1
- package/dist/components/Tabs/context.d.ts +6 -0
- package/dist/components/Textarea/SkTextarea.vue.d.ts +1 -1
- package/dist/components/Tooltip/SkTooltip.vue.d.ts +1 -1
- package/dist/composables/injectionKeys.d.ts +9 -0
- package/dist/global.d.ts +4 -0
- package/dist/index.d.ts +18 -0
- package/dist/sleekspace-ui.css +831 -277
- package/dist/sleekspace-ui.es.js +3693 -2514
- package/dist/sleekspace-ui.umd.js +3700 -2513
- package/dist/static/components/alert.d.ts +2 -1
- package/dist/static/components/avatar.d.ts +2 -1
- package/dist/static/components/breadcrumbs.d.ts +2 -1
- package/dist/static/components/button.d.ts +4 -2
- package/dist/static/components/card.d.ts +2 -1
- package/dist/static/components/checkbox.d.ts +2 -1
- package/dist/static/components/colorPicker.d.ts +2 -1
- package/dist/static/components/divider.d.ts +2 -1
- package/dist/static/components/dropdown.d.ts +2 -1
- package/dist/static/components/field.d.ts +2 -1
- package/dist/static/components/group.d.ts +2 -1
- package/dist/static/components/input.d.ts +4 -2
- package/dist/static/components/inputGroup.d.ts +8 -0
- package/dist/static/components/inputGroupAddon.d.ts +7 -0
- package/dist/static/components/navBar.d.ts +2 -1
- package/dist/static/components/numberInput.d.ts +4 -2
- package/dist/static/components/page.d.ts +2 -1
- package/dist/static/components/pagination.d.ts +2 -1
- package/dist/static/components/panel.d.ts +2 -1
- package/dist/static/components/progress.d.ts +2 -1
- package/dist/static/components/radio.d.ts +2 -1
- package/dist/static/components/select.d.ts +4 -2
- package/dist/static/components/sidebar.d.ts +2 -1
- package/dist/static/components/skeleton.d.ts +2 -1
- package/dist/static/components/slider.d.ts +2 -1
- package/dist/static/components/spinner.d.ts +2 -1
- package/dist/static/components/switchInput.d.ts +2 -1
- package/dist/static/components/table.d.ts +2 -1
- package/dist/static/components/tag.d.ts +2 -1
- package/dist/static/components/tagsInput.d.ts +2 -1
- package/dist/static/components/textarea.d.ts +2 -1
- package/dist/static/components/toolbar.d.ts +2 -1
- package/dist/static/components/tooltip.d.ts +2 -1
- package/dist/static/h.d.ts +2 -0
- package/dist/static/index.cjs.js +1 -1
- package/dist/static/index.d.ts +6 -0
- package/dist/static/index.es.js +366 -216
- package/dist/static/render.d.ts +2 -1
- package/dist/static/stringH.d.ts +2 -0
- package/dist/static/types.d.ts +5 -0
- package/dist/tailwind.css +222 -0
- package/dist/tokens.css +0 -223
- package/dist/types/corners.d.ts +1 -0
- package/llms-full.txt +14 -9
- package/package.json +6 -3
- package/src/components/Accordion/SkAccordion.vue +5 -2
- package/src/components/Accordion/SkAccordionItem.vue +7 -4
- package/src/components/Accordion/context.ts +23 -0
- package/src/components/Autocomplete/SkAutocomplete.test.ts +83 -0
- package/src/components/Autocomplete/SkAutocomplete.vue +305 -0
- package/src/components/Autocomplete/SkAutocompleteEmpty.vue +39 -0
- package/src/components/Autocomplete/SkAutocompleteGroup.vue +46 -0
- package/src/components/Autocomplete/SkAutocompleteGroupLabel.vue +39 -0
- package/src/components/Autocomplete/SkAutocompleteItem.vue +85 -0
- package/src/components/Autocomplete/SkAutocompleteSeparator.vue +39 -0
- package/src/components/Autocomplete/index.ts +13 -0
- package/src/components/Autocomplete/types.ts +10 -0
- package/src/components/Breadcrumbs/SkBreadcrumbItem.vue +8 -3
- package/src/components/Breadcrumbs/SkBreadcrumbSeparator.vue +8 -2
- package/src/components/Breadcrumbs/SkBreadcrumbs.vue +5 -2
- package/src/components/Breadcrumbs/context.ts +20 -0
- package/src/components/Button/SkButton.vue +46 -6
- package/src/components/Button/types.ts +6 -0
- package/src/components/ColorPicker/SkColorPicker.vue +27 -5
- package/src/components/ContextMenu/SkContextMenu.vue +4 -1
- package/src/components/ContextMenu/SkContextMenuSubmenu.vue +5 -2
- package/src/components/ContextMenu/context.ts +17 -0
- package/src/components/Dropdown/SkDropdown.vue +2 -1
- package/src/components/Dropdown/SkDropdownSubmenu.vue +4 -3
- package/src/components/Dropdown/context.ts +16 -0
- package/src/components/Field/SkField.test.ts +88 -0
- package/src/components/Field/SkField.vue +15 -7
- package/src/components/Input/SkInput.test.ts +61 -0
- package/src/components/Input/SkInput.vue +42 -7
- package/src/components/Input/types.ts +2 -0
- package/src/components/InputGroup/SkInputGroup.test.ts +171 -0
- package/src/components/InputGroup/SkInputGroup.vue +131 -0
- package/src/components/InputGroup/SkInputGroupAddon.test.ts +104 -0
- package/src/components/InputGroup/SkInputGroupAddon.vue +107 -0
- package/src/components/InputGroup/types.ts +27 -0
- package/src/components/Listbox/SkListbox.vue +27 -6
- package/src/components/NumberInput/SkNumberInput.vue +39 -7
- package/src/components/NumberInput/types.ts +2 -0
- package/src/components/Pagination/SkPagination.vue +6 -3
- package/src/components/Pagination/SkPaginationItem.vue +8 -5
- package/src/components/Pagination/context.ts +19 -0
- package/src/components/Panel/types.ts +3 -2
- package/src/components/Radio/SkRadio.vue +6 -3
- package/src/components/Radio/SkRadioGroup.vue +4 -2
- package/src/components/Radio/context.ts +17 -0
- package/src/components/Select/SkSelect.vue +39 -7
- package/src/components/Select/types.ts +2 -0
- package/src/components/Tabs/SkTab.vue +4 -2
- package/src/components/Tabs/SkTabList.vue +4 -2
- package/src/components/Tabs/SkTabs.vue +5 -3
- package/src/components/Tabs/context.ts +19 -0
- package/src/components/TagsInput/SkTagsInput.vue +28 -7
- package/src/components/Textarea/SkTextarea.vue +27 -6
- package/src/composables/injectionKeys.ts +52 -0
- package/src/index.ts +28 -0
- package/src/static/__tests__/parity.test.ts +2 -1
- package/src/static/__tests__/parityHarness.ts +5 -2
- package/src/static/components/__tests__/helpers.test.ts +191 -99
- package/src/static/components/alert.ts +12 -11
- package/src/static/components/avatar.ts +15 -16
- package/src/static/components/breadcrumbs.ts +3 -2
- package/src/static/components/button.ts +23 -27
- package/src/static/components/card.ts +3 -2
- package/src/static/components/checkbox.ts +11 -14
- package/src/static/components/colorPicker.ts +7 -9
- package/src/static/components/divider.ts +4 -3
- package/src/static/components/dropdown.ts +15 -6
- package/src/static/components/field.ts +32 -15
- package/src/static/components/group.ts +3 -2
- package/src/static/components/input.ts +20 -15
- package/src/static/components/inputGroup.ts +30 -0
- package/src/static/components/inputGroupAddon.ts +29 -0
- package/src/static/components/navBar.ts +30 -17
- package/src/static/components/numberInput.ts +17 -17
- package/src/static/components/page.ts +3 -2
- package/src/static/components/pagination.ts +3 -2
- package/src/static/components/panel.ts +3 -2
- package/src/static/components/progress.ts +3 -2
- package/src/static/components/radio.ts +14 -20
- package/src/static/components/select.ts +18 -15
- package/src/static/components/sidebar.ts +9 -13
- package/src/static/components/skeleton.ts +7 -10
- package/src/static/components/slider.ts +7 -9
- package/src/static/components/spinner.ts +22 -22
- package/src/static/components/switchInput.ts +12 -14
- package/src/static/components/table.ts +8 -10
- package/src/static/components/tag.ts +17 -11
- package/src/static/components/tagsInput.ts +3 -3
- package/src/static/components/textarea.ts +8 -13
- package/src/static/components/toolbar.ts +7 -10
- package/src/static/components/tooltip.ts +3 -2
- package/src/static/generated/defaults.ts +24 -9
- package/src/static/generated/propTypes.ts +18 -2
- package/src/static/h.ts +16 -0
- package/src/static/index.ts +8 -0
- package/src/static/render.test.ts +14 -10
- package/src/static/render.ts +33 -18
- package/src/static/specs.test.ts +1 -0
- package/src/static/specs.ts +22 -2
- package/src/static/stringH.ts +104 -0
- package/src/static/types.ts +25 -0
- package/src/styles/components/_autocomplete.scss +498 -0
- package/src/styles/components/_button.scss +55 -6
- package/src/styles/components/_index.scss +2 -0
- package/src/styles/components/_input-group.scss +292 -0
- package/src/styles/components/_input.scss +57 -9
- package/src/styles/components/_number-input.scss +84 -18
- package/src/styles/components/_select.scss +56 -9
- package/src/styles/mixins/_cut-border.scss +83 -0
- package/src/styles/tailwind.scss +262 -0
- package/src/styles/tokens.scss +8 -255
- package/src/types/corners.ts +10 -0
- package/src/utils/slots.test.ts +89 -0
- package/src/utils/slots.ts +6 -1
- package/web-types.json +382 -12
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
<!----------------------------------------------------------------------------------------------------------------------
|
|
2
|
+
- AutocompleteSeparator Component
|
|
3
|
+
--------------------------------------------------------------------------------------------------------------------->
|
|
4
|
+
|
|
5
|
+
<template>
|
|
6
|
+
<AutocompleteSeparator class="sk-autocomplete-separator" />
|
|
7
|
+
</template>
|
|
8
|
+
|
|
9
|
+
<!--------------------------------------------------------------------------------------------------------------------->
|
|
10
|
+
|
|
11
|
+
<style lang="scss" scoped>
|
|
12
|
+
// Component styles are in /src/styles/components/_autocomplete.scss
|
|
13
|
+
</style>
|
|
14
|
+
|
|
15
|
+
<!--------------------------------------------------------------------------------------------------------------------->
|
|
16
|
+
|
|
17
|
+
<script setup lang="ts">
|
|
18
|
+
/**
|
|
19
|
+
* @component SkAutocompleteSeparator
|
|
20
|
+
* @description A visual divider for organizing suggestions within an SkAutocomplete dropdown. Renders
|
|
21
|
+
* as a horizontal line between items with appropriate spacing.
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```vue
|
|
25
|
+
* <SkAutocomplete v-model="query">
|
|
26
|
+
* <SkAutocompleteItem value="recent1">Recent search 1</SkAutocompleteItem>
|
|
27
|
+
* <SkAutocompleteItem value="recent2">Recent search 2</SkAutocompleteItem>
|
|
28
|
+
* <SkAutocompleteSeparator />
|
|
29
|
+
* <SkAutocompleteItem value="popular">Popular searches...</SkAutocompleteItem>
|
|
30
|
+
* </SkAutocomplete>
|
|
31
|
+
* ```
|
|
32
|
+
*
|
|
33
|
+
* @slot - Not applicable. This component does not accept slot content.
|
|
34
|
+
*/
|
|
35
|
+
|
|
36
|
+
import { AutocompleteSeparator } from 'reka-ui';
|
|
37
|
+
</script>
|
|
38
|
+
|
|
39
|
+
<!--------------------------------------------------------------------------------------------------------------------->
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
2
|
+
// Autocomplete Component Exports
|
|
3
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
4
|
+
|
|
5
|
+
export { default as SkAutocomplete } from './SkAutocomplete.vue';
|
|
6
|
+
export { default as SkAutocompleteEmpty } from './SkAutocompleteEmpty.vue';
|
|
7
|
+
export { default as SkAutocompleteGroup } from './SkAutocompleteGroup.vue';
|
|
8
|
+
export { default as SkAutocompleteGroupLabel } from './SkAutocompleteGroupLabel.vue';
|
|
9
|
+
export { default as SkAutocompleteItem } from './SkAutocompleteItem.vue';
|
|
10
|
+
export { default as SkAutocompleteSeparator } from './SkAutocompleteSeparator.vue';
|
|
11
|
+
export type { SkAutocompleteKind, SkAutocompleteSize } from './types';
|
|
12
|
+
|
|
13
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
2
|
+
// Autocomplete Component Types
|
|
3
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
4
|
+
|
|
5
|
+
import type { ComponentKind, ComponentSize } from '@/types';
|
|
6
|
+
|
|
7
|
+
export type SkAutocompleteKind = ComponentKind;
|
|
8
|
+
export type SkAutocompleteSize = ComponentSize;
|
|
9
|
+
|
|
10
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
@@ -59,7 +59,10 @@
|
|
|
59
59
|
import { RouterLink } from 'vue-router';
|
|
60
60
|
|
|
61
61
|
// Types
|
|
62
|
-
import type { SkBreadcrumbItemProps
|
|
62
|
+
import type { SkBreadcrumbItemProps } from './types';
|
|
63
|
+
|
|
64
|
+
// Context
|
|
65
|
+
import { BREADCRUMBS_KIND_KEY } from './context';
|
|
63
66
|
|
|
64
67
|
//------------------------------------------------------------------------------------------------------------------
|
|
65
68
|
|
|
@@ -106,7 +109,9 @@
|
|
|
106
109
|
|
|
107
110
|
//------------------------------------------------------------------------------------------------------------------
|
|
108
111
|
|
|
109
|
-
|
|
112
|
+
// BREADCRUMBS_KIND_KEY carries a Ref<SkBreadcrumbsKind | undefined>, so we read .value below.
|
|
113
|
+
// (Pre-typed-key code mistakenly treated this as a plain string and rendered `sk-[object Object]`.)
|
|
114
|
+
const kindRef = inject(BREADCRUMBS_KIND_KEY, computed(() => undefined));
|
|
110
115
|
|
|
111
116
|
//------------------------------------------------------------------------------------------------------------------
|
|
112
117
|
|
|
@@ -129,7 +134,7 @@
|
|
|
129
134
|
|
|
130
135
|
const linkClasses = computed(() => ({
|
|
131
136
|
'sk-breadcrumb-link': true,
|
|
132
|
-
[`sk-${
|
|
137
|
+
[`sk-${ kindRef.value ?? 'neutral' }`]: true,
|
|
133
138
|
}));
|
|
134
139
|
|
|
135
140
|
//------------------------------------------------------------------------------------------------------------------
|
|
@@ -34,6 +34,9 @@
|
|
|
34
34
|
|
|
35
35
|
import { computed, inject } from 'vue';
|
|
36
36
|
|
|
37
|
+
// Context
|
|
38
|
+
import { BREADCRUMBS_SEPARATOR_KEY } from './context';
|
|
39
|
+
|
|
37
40
|
//------------------------------------------------------------------------------------------------------------------
|
|
38
41
|
|
|
39
42
|
export interface SkBreadcrumbSeparatorComponentProps
|
|
@@ -55,11 +58,14 @@
|
|
|
55
58
|
|
|
56
59
|
//------------------------------------------------------------------------------------------------------------------
|
|
57
60
|
|
|
58
|
-
|
|
61
|
+
// BREADCRUMBS_SEPARATOR_KEY carries a Ref<string | undefined>, so we read .value below.
|
|
62
|
+
// (Pre-typed-key code mistakenly treated this as a plain string and rendered `[object Object]`
|
|
63
|
+
// for the separator inside an SkBreadcrumbs.)
|
|
64
|
+
const parentSeparator = inject(BREADCRUMBS_SEPARATOR_KEY, computed(() => undefined));
|
|
59
65
|
|
|
60
66
|
//------------------------------------------------------------------------------------------------------------------
|
|
61
67
|
|
|
62
|
-
const displaySeparator = computed<string>(() => props.separator ?? parentSeparator);
|
|
68
|
+
const displaySeparator = computed<string>(() => props.separator ?? parentSeparator.value ?? '/');
|
|
63
69
|
|
|
64
70
|
//------------------------------------------------------------------------------------------------------------------
|
|
65
71
|
</script>
|
|
@@ -77,6 +77,9 @@
|
|
|
77
77
|
// Composables
|
|
78
78
|
import { useCustomColors } from '@/composables/useCustomColors';
|
|
79
79
|
|
|
80
|
+
// Context
|
|
81
|
+
import { BREADCRUMBS_KIND_KEY, BREADCRUMBS_SEPARATOR_KEY } from './context';
|
|
82
|
+
|
|
80
83
|
//------------------------------------------------------------------------------------------------------------------
|
|
81
84
|
|
|
82
85
|
const props = withDefaults(defineProps<SkBreadcrumbsComponentProps>(), {
|
|
@@ -92,8 +95,8 @@
|
|
|
92
95
|
|
|
93
96
|
//------------------------------------------------------------------------------------------------------------------
|
|
94
97
|
|
|
95
|
-
provide(
|
|
96
|
-
provide(
|
|
98
|
+
provide(BREADCRUMBS_KIND_KEY, toRef(() => props.kind));
|
|
99
|
+
provide(BREADCRUMBS_SEPARATOR_KEY, toRef(() => props.separator));
|
|
97
100
|
|
|
98
101
|
//------------------------------------------------------------------------------------------------------------------
|
|
99
102
|
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
2
|
+
// Breadcrumbs Context
|
|
3
|
+
//
|
|
4
|
+
// Injection keys for SkBreadcrumbItem and SkBreadcrumbSeparator descendants to inherit kind and
|
|
5
|
+
// separator from the surrounding SkBreadcrumbs without manual wiring.
|
|
6
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
7
|
+
|
|
8
|
+
import type { InjectionKey, Ref } from 'vue';
|
|
9
|
+
|
|
10
|
+
import type { SkBreadcrumbsKind } from './types';
|
|
11
|
+
|
|
12
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
13
|
+
|
|
14
|
+
export const BREADCRUMBS_KIND_KEY : InjectionKey<Ref<SkBreadcrumbsKind | undefined>>
|
|
15
|
+
= Symbol('sk-breadcrumbs-kind');
|
|
16
|
+
|
|
17
|
+
export const BREADCRUMBS_SEPARATOR_KEY : InjectionKey<Ref<string | undefined>>
|
|
18
|
+
= Symbol('sk-breadcrumbs-separator');
|
|
19
|
+
|
|
20
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
@@ -63,13 +63,20 @@
|
|
|
63
63
|
* @slot icon - Icon for icon-only buttons. When used without the default slot, creates a square icon button.
|
|
64
64
|
*/
|
|
65
65
|
|
|
66
|
-
import { type Slots, computed, toRef, useSlots } from 'vue';
|
|
66
|
+
import { type Slots, computed, inject, toRef, useSlots } from 'vue';
|
|
67
67
|
|
|
68
68
|
// Types
|
|
69
69
|
import type { ComponentCustomColors } from '@/types';
|
|
70
|
-
import type { SkButtonKind, SkButtonSize, SkButtonType, SkButtonVariant } from './types';
|
|
70
|
+
import type { SkButtonCorner, SkButtonKind, SkButtonSize, SkButtonType, SkButtonVariant } from './types';
|
|
71
71
|
|
|
72
72
|
// Composables
|
|
73
|
+
import {
|
|
74
|
+
NO_KIND,
|
|
75
|
+
NO_SIZE,
|
|
76
|
+
inheritedKindKey,
|
|
77
|
+
inputGroupSizeKey,
|
|
78
|
+
validationKindKey,
|
|
79
|
+
} from '@/composables/injectionKeys';
|
|
73
80
|
import { useCustomColors } from '@/composables/useCustomColors';
|
|
74
81
|
|
|
75
82
|
// Utils
|
|
@@ -143,6 +150,13 @@
|
|
|
143
150
|
*/
|
|
144
151
|
dense ?: boolean;
|
|
145
152
|
|
|
153
|
+
/**
|
|
154
|
+
* Which corners receive the beveled cut. Pass an empty array for square corners.
|
|
155
|
+
* When omitted, defaults to the button's standalone visual (`top-left` + `bottom-right`).
|
|
156
|
+
* @default undefined (renders as ['top-left', 'bottom-right'])
|
|
157
|
+
*/
|
|
158
|
+
corners ?: SkButtonCorner[];
|
|
159
|
+
|
|
146
160
|
/**
|
|
147
161
|
* URL for the button to navigate to. When provided, the button renders as an `<a>` element
|
|
148
162
|
* instead of a `<button>`. Use for external links or simple navigation that doesn't require
|
|
@@ -164,13 +178,14 @@
|
|
|
164
178
|
|
|
165
179
|
const props = withDefaults(defineProps<SkButtonComponentProps>(), {
|
|
166
180
|
type: 'button',
|
|
167
|
-
kind:
|
|
181
|
+
kind: undefined,
|
|
168
182
|
variant: 'solid',
|
|
169
|
-
size:
|
|
183
|
+
size: undefined,
|
|
170
184
|
disabled: false,
|
|
171
185
|
loading: false,
|
|
172
186
|
pressed: false,
|
|
173
187
|
dense: false,
|
|
188
|
+
corners: undefined,
|
|
174
189
|
href: undefined,
|
|
175
190
|
to: undefined,
|
|
176
191
|
});
|
|
@@ -181,6 +196,27 @@
|
|
|
181
196
|
|
|
182
197
|
//------------------------------------------------------------------------------------------------------------------
|
|
183
198
|
|
|
199
|
+
const validationKind = inject(validationKindKey, NO_KIND);
|
|
200
|
+
const inheritedKind = inject(inheritedKindKey, NO_KIND);
|
|
201
|
+
const inputGroupSize = inject(inputGroupSizeKey, NO_SIZE);
|
|
202
|
+
|
|
203
|
+
const effectiveKind = computed<SkButtonKind>(() =>
|
|
204
|
+
{
|
|
205
|
+
if(validationKind.value !== undefined) { return validationKind.value; }
|
|
206
|
+
if(props.kind !== undefined) { return props.kind; }
|
|
207
|
+
if(inheritedKind.value !== undefined) { return inheritedKind.value; }
|
|
208
|
+
return 'neutral';
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
const effectiveSize = computed<SkButtonSize>(() =>
|
|
212
|
+
{
|
|
213
|
+
if(props.size !== undefined) { return props.size; }
|
|
214
|
+
if(inputGroupSize.value !== undefined) { return inputGroupSize.value; }
|
|
215
|
+
return 'md';
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
//------------------------------------------------------------------------------------------------------------------
|
|
219
|
+
|
|
184
220
|
// Determine which component to render
|
|
185
221
|
const componentTag = computed<string>(() =>
|
|
186
222
|
{
|
|
@@ -206,13 +242,17 @@
|
|
|
206
242
|
|
|
207
243
|
return {
|
|
208
244
|
'sk-button': true,
|
|
209
|
-
[`sk-${
|
|
245
|
+
[`sk-${ effectiveKind.value }`]: true,
|
|
210
246
|
[`sk-${ props.variant }`]: true,
|
|
211
|
-
[`sk-${
|
|
247
|
+
[`sk-${ effectiveSize.value }`]: true,
|
|
212
248
|
'sk-loading': props.loading,
|
|
213
249
|
'sk-pressed': props.pressed,
|
|
214
250
|
'sk-dense': props.dense,
|
|
215
251
|
'sk-icon-only': isIconOnly,
|
|
252
|
+
'sk-cut-top-left': props.corners?.includes('top-left') ?? false,
|
|
253
|
+
'sk-cut-top-right': props.corners?.includes('top-right') ?? false,
|
|
254
|
+
'sk-cut-bottom-right': props.corners?.includes('bottom-right') ?? false,
|
|
255
|
+
'sk-cut-bottom-left': props.corners?.includes('bottom-left') ?? false,
|
|
216
256
|
};
|
|
217
257
|
});
|
|
218
258
|
|
|
@@ -4,11 +4,17 @@
|
|
|
4
4
|
|
|
5
5
|
import type { ComponentKind, ComponentSize, ComponentVariant } from '@/types';
|
|
6
6
|
|
|
7
|
+
// Types
|
|
8
|
+
import type { SkCorner } from '@/types/corners';
|
|
9
|
+
|
|
7
10
|
//----------------------------------------------------------------------------------------------------------------------
|
|
8
11
|
|
|
9
12
|
// HTML button type attribute
|
|
10
13
|
export type SkButtonType = 'button' | 'submit' | 'reset';
|
|
11
14
|
|
|
15
|
+
// Button corner type (controls which corners receive the beveled cut)
|
|
16
|
+
export type SkButtonCorner = SkCorner;
|
|
17
|
+
|
|
12
18
|
// Button semantic kinds (uses common types)
|
|
13
19
|
export type SkButtonKind = ComponentKind;
|
|
14
20
|
|
|
@@ -226,7 +226,7 @@
|
|
|
226
226
|
<!--------------------------------------------------------------------------------------------------------------------->
|
|
227
227
|
|
|
228
228
|
<script setup lang="ts">
|
|
229
|
-
import { type Component,
|
|
229
|
+
import { type Component, computed, inject, ref, toRef } from 'vue';
|
|
230
230
|
import {
|
|
231
231
|
type ColorObject,
|
|
232
232
|
ColorPickerCanvas,
|
|
@@ -251,6 +251,13 @@
|
|
|
251
251
|
import type { SkColorPickerFormat, SkColorPickerKind, SkColorPickerSize } from './types';
|
|
252
252
|
|
|
253
253
|
// Composables
|
|
254
|
+
import {
|
|
255
|
+
NO_KIND,
|
|
256
|
+
NO_SIZE,
|
|
257
|
+
inheritedKindKey,
|
|
258
|
+
inputGroupSizeKey,
|
|
259
|
+
validationKindKey,
|
|
260
|
+
} from '@/composables/injectionKeys';
|
|
254
261
|
import { useCustomColors } from '@/composables/useCustomColors';
|
|
255
262
|
import { usePortalContext } from '@/composables/usePortalContext';
|
|
256
263
|
|
|
@@ -283,7 +290,7 @@
|
|
|
283
290
|
|
|
284
291
|
const props = withDefaults(defineProps<SkColorPickerComponentProps>(), {
|
|
285
292
|
kind: undefined,
|
|
286
|
-
size:
|
|
293
|
+
size: undefined,
|
|
287
294
|
format: 'hexa',
|
|
288
295
|
showAlpha: true,
|
|
289
296
|
disabled: false,
|
|
@@ -299,19 +306,34 @@
|
|
|
299
306
|
|
|
300
307
|
const { theme } = usePortalContext();
|
|
301
308
|
|
|
302
|
-
const
|
|
309
|
+
const validationKind = inject(validationKindKey, NO_KIND);
|
|
310
|
+
const inheritedKind = inject(inheritedKindKey, NO_KIND);
|
|
311
|
+
const inputGroupSize = inject(inputGroupSizeKey, NO_SIZE);
|
|
303
312
|
const displayFormat = ref<DisplayFormat>('Hex');
|
|
304
313
|
|
|
305
314
|
//------------------------------------------------------------------------------------------------------------------
|
|
306
315
|
|
|
307
|
-
const effectiveKind = computed(() =>
|
|
316
|
+
const effectiveKind = computed<SkColorPickerKind>(() =>
|
|
317
|
+
{
|
|
318
|
+
if(validationKind.value !== undefined) { return validationKind.value; }
|
|
319
|
+
if(props.kind !== undefined) { return props.kind; }
|
|
320
|
+
if(inheritedKind.value !== undefined) { return inheritedKind.value; }
|
|
321
|
+
return 'neutral';
|
|
322
|
+
});
|
|
323
|
+
|
|
324
|
+
const effectiveSize = computed<SkColorPickerSize>(() =>
|
|
325
|
+
{
|
|
326
|
+
if(props.size !== undefined) { return props.size; }
|
|
327
|
+
if(inputGroupSize.value !== undefined) { return inputGroupSize.value; }
|
|
328
|
+
return 'md';
|
|
329
|
+
});
|
|
308
330
|
|
|
309
331
|
//------------------------------------------------------------------------------------------------------------------
|
|
310
332
|
|
|
311
333
|
const wrapperClasses = computed(() => ({
|
|
312
334
|
'sk-color-picker': true,
|
|
313
335
|
[`sk-${ effectiveKind.value }`]: true,
|
|
314
|
-
[`sk-${
|
|
336
|
+
[`sk-${ effectiveSize.value }`]: true,
|
|
315
337
|
'sk-disabled': props.disabled,
|
|
316
338
|
}));
|
|
317
339
|
|
|
@@ -45,6 +45,9 @@
|
|
|
45
45
|
import { useCustomColors } from '@/composables/useCustomColors';
|
|
46
46
|
import { usePortalContext } from '@/composables/usePortalContext';
|
|
47
47
|
|
|
48
|
+
// Context
|
|
49
|
+
import { CONTEXT_MENU_KIND_KEY } from './context';
|
|
50
|
+
|
|
48
51
|
//------------------------------------------------------------------------------------------------------------------
|
|
49
52
|
|
|
50
53
|
export interface SkContextMenuComponentProps extends ComponentCustomColors
|
|
@@ -62,7 +65,7 @@
|
|
|
62
65
|
|
|
63
66
|
const { theme } = usePortalContext();
|
|
64
67
|
|
|
65
|
-
provide(
|
|
68
|
+
provide(CONTEXT_MENU_KIND_KEY, computed(() => props.kind));
|
|
66
69
|
|
|
67
70
|
//------------------------------------------------------------------------------------------------------------------
|
|
68
71
|
|
|
@@ -53,6 +53,9 @@
|
|
|
53
53
|
// Composables
|
|
54
54
|
import { usePortalContext } from '@/composables/usePortalContext';
|
|
55
55
|
|
|
56
|
+
// Context
|
|
57
|
+
import { CONTEXT_MENU_KIND_KEY } from './context';
|
|
58
|
+
|
|
56
59
|
//------------------------------------------------------------------------------------------------------------------
|
|
57
60
|
|
|
58
61
|
export interface SkContextMenuSubmenuComponentProps
|
|
@@ -71,11 +74,11 @@
|
|
|
71
74
|
|
|
72
75
|
const { theme } = usePortalContext();
|
|
73
76
|
|
|
74
|
-
const parentKind = inject
|
|
77
|
+
const parentKind = inject(CONTEXT_MENU_KIND_KEY, computed(() => undefined));
|
|
75
78
|
|
|
76
79
|
//------------------------------------------------------------------------------------------------------------------
|
|
77
80
|
|
|
78
|
-
const effectiveKind = computed(() => props.kind
|
|
81
|
+
const effectiveKind = computed<SkContextMenuKind>(() => props.kind ?? parentKind.value ?? 'neutral');
|
|
79
82
|
|
|
80
83
|
//------------------------------------------------------------------------------------------------------------------
|
|
81
84
|
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
2
|
+
// ContextMenu Context
|
|
3
|
+
//
|
|
4
|
+
// Injection key for nested SkContextMenuSubmenu descendants to inherit the surrounding
|
|
5
|
+
// SkContextMenu's kind without manual wiring.
|
|
6
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
7
|
+
|
|
8
|
+
import type { ComputedRef, InjectionKey } from 'vue';
|
|
9
|
+
|
|
10
|
+
import type { SkContextMenuKind } from './types';
|
|
11
|
+
|
|
12
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
13
|
+
|
|
14
|
+
export const CONTEXT_MENU_KIND_KEY : InjectionKey<ComputedRef<SkContextMenuKind | undefined>>
|
|
15
|
+
= Symbol('sk-context-menu-kind');
|
|
16
|
+
|
|
17
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
@@ -94,6 +94,7 @@
|
|
|
94
94
|
|
|
95
95
|
// Context
|
|
96
96
|
import { NAVBAR_SIZE_KEY } from '../NavBar/context';
|
|
97
|
+
import { DROPDOWN_KIND_KEY } from './context';
|
|
97
98
|
|
|
98
99
|
//------------------------------------------------------------------------------------------------------------------
|
|
99
100
|
|
|
@@ -170,7 +171,7 @@
|
|
|
170
171
|
const effectiveSize = computed<SkDropdownSize>(() => props.size ?? navbarSize?.value ?? 'md');
|
|
171
172
|
|
|
172
173
|
// Provide kind for submenus (reactive computed so changes propagate)
|
|
173
|
-
provide(
|
|
174
|
+
provide(DROPDOWN_KIND_KEY, computed(() => props.kind));
|
|
174
175
|
|
|
175
176
|
//------------------------------------------------------------------------------------------------------------------
|
|
176
177
|
|
|
@@ -75,6 +75,8 @@
|
|
|
75
75
|
// Types
|
|
76
76
|
import type { SkDropdownKind } from './types';
|
|
77
77
|
|
|
78
|
+
import { DROPDOWN_KIND_KEY } from './context';
|
|
79
|
+
|
|
78
80
|
//------------------------------------------------------------------------------------------------------------------
|
|
79
81
|
|
|
80
82
|
export interface SkDropdownSubmenuComponentProps
|
|
@@ -105,12 +107,11 @@
|
|
|
105
107
|
// Handle portal context (theme injection/re-provision for nested portal components)
|
|
106
108
|
const { theme } = usePortalContext();
|
|
107
109
|
|
|
108
|
-
|
|
109
|
-
const parentKind = inject<any>('dropdown-kind', computed(() => 'neutral'));
|
|
110
|
+
const parentKind = inject(DROPDOWN_KIND_KEY, computed(() => undefined));
|
|
110
111
|
|
|
111
112
|
//------------------------------------------------------------------------------------------------------------------
|
|
112
113
|
|
|
113
|
-
const effectiveKind = computed(() => props.kind
|
|
114
|
+
const effectiveKind = computed<SkDropdownKind>(() => props.kind ?? parentKind.value ?? 'neutral');
|
|
114
115
|
|
|
115
116
|
//------------------------------------------------------------------------------------------------------------------
|
|
116
117
|
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
2
|
+
// Dropdown Context
|
|
3
|
+
//
|
|
4
|
+
// Injection key for nested SkDropdownSubmenu descendants to inherit the surrounding SkDropdown's
|
|
5
|
+
// kind without manual wiring.
|
|
6
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
7
|
+
|
|
8
|
+
import type { ComputedRef, InjectionKey } from 'vue';
|
|
9
|
+
|
|
10
|
+
import type { SkDropdownKind } from './types';
|
|
11
|
+
|
|
12
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
13
|
+
|
|
14
|
+
export const DROPDOWN_KIND_KEY : InjectionKey<ComputedRef<SkDropdownKind | undefined>> = Symbol('sk-dropdown-kind');
|
|
15
|
+
|
|
16
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
2
|
+
// SkField Tests — focuses on the validation-kind provide contract.
|
|
3
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
4
|
+
|
|
5
|
+
import { computed, defineComponent, h, inject } from 'vue';
|
|
6
|
+
import { mount } from '@vue/test-utils';
|
|
7
|
+
import { describe, expect, it } from 'vitest';
|
|
8
|
+
|
|
9
|
+
import { inheritedKindKey, validationKindKey } from '@/composables/injectionKeys';
|
|
10
|
+
|
|
11
|
+
import SkField from './SkField.vue';
|
|
12
|
+
|
|
13
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
14
|
+
|
|
15
|
+
// Probe component that surfaces the validation-kind / inherited-kind it sees as data attributes.
|
|
16
|
+
// Lets us assert what SkField actually puts on each channel without relying on a leaf form
|
|
17
|
+
// component's class output.
|
|
18
|
+
const Probe = defineComponent({
|
|
19
|
+
setup()
|
|
20
|
+
{
|
|
21
|
+
const validation = inject(validationKindKey, computed(() => 'NONE'));
|
|
22
|
+
const inherited = inject(inheritedKindKey, computed(() => 'NONE'));
|
|
23
|
+
return () => h('div', {
|
|
24
|
+
'data-validation': validation.value ?? 'undef',
|
|
25
|
+
'data-inherited': inherited.value ?? 'undef',
|
|
26
|
+
});
|
|
27
|
+
},
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
31
|
+
|
|
32
|
+
function mountField(props : Record<string, unknown> = {}) : ReturnType<typeof mount>
|
|
33
|
+
{
|
|
34
|
+
return mount(SkField, {
|
|
35
|
+
props,
|
|
36
|
+
slots: { default: () => h(Probe) },
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
41
|
+
|
|
42
|
+
describe('SkField validation-kind contract', () =>
|
|
43
|
+
{
|
|
44
|
+
it('provides undefined on validation-kind when state is null', () =>
|
|
45
|
+
{
|
|
46
|
+
const wrapper = mountField({ state: null });
|
|
47
|
+
expect(wrapper.find('[data-validation]').attributes('data-validation')).toBe('undef');
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it('provides undefined on validation-kind when state is omitted', () =>
|
|
51
|
+
{
|
|
52
|
+
const wrapper = mountField();
|
|
53
|
+
expect(wrapper.find('[data-validation]').attributes('data-validation')).toBe('undef');
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it('provides validKind on validation-kind when state is true', () =>
|
|
57
|
+
{
|
|
58
|
+
const wrapper = mountField({ state: true });
|
|
59
|
+
expect(wrapper.find('[data-validation]').attributes('data-validation')).toBe('success');
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it('provides invalidKind on validation-kind when state is false', () =>
|
|
63
|
+
{
|
|
64
|
+
const wrapper = mountField({ state: false });
|
|
65
|
+
expect(wrapper.find('[data-validation]').attributes('data-validation')).toBe('danger');
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it('honors custom validKind / invalidKind', () =>
|
|
69
|
+
{
|
|
70
|
+
const valid = mountField({ state: true, validKind: 'accent' });
|
|
71
|
+
expect(valid.find('[data-validation]').attributes('data-validation')).toBe('accent');
|
|
72
|
+
|
|
73
|
+
const invalid = mountField({ state: false, invalidKind: 'warning' });
|
|
74
|
+
expect(invalid.find('[data-validation]').attributes('data-validation')).toBe('warning');
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it('does NOT touch the inherited-kind channel', () =>
|
|
78
|
+
{
|
|
79
|
+
// Validation override and ambient default live on separate channels. SkField must not
|
|
80
|
+
// bleed into inherited-kind, or an InputGroup further down the tree would pick up the
|
|
81
|
+
// validation kind as if it were an ambient default. The probe falls back to 'NONE' when
|
|
82
|
+
// no provider exists for inherited-kind — that's the assertion.
|
|
83
|
+
const wrapper = mountField({ state: false });
|
|
84
|
+
expect(wrapper.find('[data-inherited]').attributes('data-inherited')).toBe('NONE');
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
@@ -58,8 +58,12 @@
|
|
|
58
58
|
import { computed, provide } from 'vue';
|
|
59
59
|
|
|
60
60
|
// Types
|
|
61
|
+
import type { ComponentKind } from '@/types';
|
|
61
62
|
import type { SkFieldLabelPosition } from './types';
|
|
62
63
|
|
|
64
|
+
// Composables
|
|
65
|
+
import { validationKindKey } from '@/composables/injectionKeys';
|
|
66
|
+
|
|
63
67
|
//------------------------------------------------------------------------------------------------------------------
|
|
64
68
|
|
|
65
69
|
export interface SkFieldComponentProps
|
|
@@ -127,7 +131,7 @@
|
|
|
127
131
|
* inputs via Vue's provide/inject system.
|
|
128
132
|
* @default 'success'
|
|
129
133
|
*/
|
|
130
|
-
validKind ?:
|
|
134
|
+
validKind ?: ComponentKind;
|
|
131
135
|
|
|
132
136
|
/**
|
|
133
137
|
* Semantic kind to apply to the child input when `state` is `false` (invalid). Typically
|
|
@@ -135,7 +139,7 @@
|
|
|
135
139
|
* inputs via Vue's provide/inject system.
|
|
136
140
|
* @default 'danger'
|
|
137
141
|
*/
|
|
138
|
-
invalidKind ?:
|
|
142
|
+
invalidKind ?: ComponentKind;
|
|
139
143
|
}
|
|
140
144
|
|
|
141
145
|
//------------------------------------------------------------------------------------------------------------------
|
|
@@ -189,8 +193,10 @@
|
|
|
189
193
|
|
|
190
194
|
//------------------------------------------------------------------------------------------------------------------
|
|
191
195
|
|
|
192
|
-
// Determine the kind to apply based on state prop
|
|
193
|
-
|
|
196
|
+
// Determine the kind to apply based on state prop. Only emits a non-undefined value when the
|
|
197
|
+
// dev opted into validation by setting `state`; otherwise children fall through to their own
|
|
198
|
+
// kind prop / inherited-kind / default.
|
|
199
|
+
const effectiveKind = computed<ComponentKind | undefined>(() =>
|
|
194
200
|
{
|
|
195
201
|
if(props.state === true)
|
|
196
202
|
{
|
|
@@ -200,13 +206,15 @@
|
|
|
200
206
|
{
|
|
201
207
|
return props.invalidKind;
|
|
202
208
|
}
|
|
203
|
-
return undefined;
|
|
209
|
+
return undefined;
|
|
204
210
|
});
|
|
205
211
|
|
|
206
212
|
//------------------------------------------------------------------------------------------------------------------
|
|
207
213
|
|
|
208
|
-
//
|
|
209
|
-
|
|
214
|
+
// Validation channel: always wins over the child's prop and any inherited-kind ambient
|
|
215
|
+
// default. Only carries a value when `state` is set, so the absence of a state prop leaves
|
|
216
|
+
// children fully in control.
|
|
217
|
+
provide(validationKindKey, effectiveKind);
|
|
210
218
|
|
|
211
219
|
//------------------------------------------------------------------------------------------------------------------
|
|
212
220
|
|