@skewedaspect/sleekspace-ui 0.9.0 → 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.
Files changed (210) hide show
  1. package/dist/components/Accordion/context.d.ts +4 -0
  2. package/dist/components/Autocomplete/SkAutocomplete.vue.d.ts +87 -0
  3. package/dist/components/Autocomplete/SkAutocompleteEmpty.vue.d.ts +17 -0
  4. package/dist/components/Autocomplete/SkAutocompleteGroup.vue.d.ts +17 -0
  5. package/dist/components/Autocomplete/SkAutocompleteGroupLabel.vue.d.ts +17 -0
  6. package/dist/components/Autocomplete/SkAutocompleteItem.vue.d.ts +39 -0
  7. package/dist/components/Autocomplete/SkAutocompleteSeparator.vue.d.ts +2 -0
  8. package/dist/components/Autocomplete/index.d.ts +7 -0
  9. package/dist/components/Autocomplete/types.d.ts +3 -0
  10. package/dist/components/Breadcrumbs/context.d.ts +4 -0
  11. package/dist/components/Button/SkButton.vue.d.ts +8 -1
  12. package/dist/components/Button/types.d.ts +2 -0
  13. package/dist/components/Card/SkCard.vue.d.ts +1 -1
  14. package/dist/components/ContextMenu/context.d.ts +3 -0
  15. package/dist/components/Dropdown/SkDropdown.vue.d.ts +1 -1
  16. package/dist/components/Dropdown/context.d.ts +3 -0
  17. package/dist/components/Field/SkField.vue.d.ts +7 -6
  18. package/dist/components/Input/SkInput.vue.d.ts +9 -2
  19. package/dist/components/Input/types.d.ts +2 -0
  20. package/dist/components/InputGroup/SkInputGroup.vue.d.ts +23 -0
  21. package/dist/components/InputGroup/SkInputGroupAddon.vue.d.ts +33 -0
  22. package/dist/components/InputGroup/types.d.ts +13 -0
  23. package/dist/components/NumberInput/SkNumberInput.vue.d.ts +15 -1
  24. package/dist/components/NumberInput/types.d.ts +2 -0
  25. package/dist/components/Pagination/context.d.ts +5 -0
  26. package/dist/components/Panel/SkPanel.vue.d.ts +1 -1
  27. package/dist/components/Panel/types.d.ts +2 -1
  28. package/dist/components/Radio/context.d.ts +4 -0
  29. package/dist/components/Select/SkSelect.vue.d.ts +7 -1
  30. package/dist/components/Select/types.d.ts +2 -0
  31. package/dist/components/Sidebar/SkSidebar.vue.d.ts +1 -1
  32. package/dist/components/Tabs/context.d.ts +6 -0
  33. package/dist/components/Textarea/SkTextarea.vue.d.ts +1 -1
  34. package/dist/components/Tooltip/SkTooltip.vue.d.ts +1 -1
  35. package/dist/composables/injectionKeys.d.ts +9 -0
  36. package/dist/global.d.ts +4 -0
  37. package/dist/index.d.ts +18 -0
  38. package/dist/sleekspace-ui.css +836 -280
  39. package/dist/sleekspace-ui.es.js +3759 -2545
  40. package/dist/sleekspace-ui.umd.js +3765 -2543
  41. package/dist/static/components/alert.d.ts +2 -1
  42. package/dist/static/components/avatar.d.ts +2 -1
  43. package/dist/static/components/breadcrumbs.d.ts +2 -1
  44. package/dist/static/components/button.d.ts +4 -2
  45. package/dist/static/components/card.d.ts +2 -1
  46. package/dist/static/components/checkbox.d.ts +2 -1
  47. package/dist/static/components/colorPicker.d.ts +2 -1
  48. package/dist/static/components/divider.d.ts +2 -1
  49. package/dist/static/components/dropdown.d.ts +2 -1
  50. package/dist/static/components/field.d.ts +2 -1
  51. package/dist/static/components/group.d.ts +2 -1
  52. package/dist/static/components/input.d.ts +4 -2
  53. package/dist/static/components/inputGroup.d.ts +8 -0
  54. package/dist/static/components/inputGroupAddon.d.ts +7 -0
  55. package/dist/static/components/navBar.d.ts +2 -1
  56. package/dist/static/components/numberInput.d.ts +4 -2
  57. package/dist/static/components/page.d.ts +2 -1
  58. package/dist/static/components/pagination.d.ts +2 -1
  59. package/dist/static/components/panel.d.ts +2 -1
  60. package/dist/static/components/progress.d.ts +2 -1
  61. package/dist/static/components/radio.d.ts +2 -1
  62. package/dist/static/components/select.d.ts +4 -2
  63. package/dist/static/components/sidebar.d.ts +2 -1
  64. package/dist/static/components/skeleton.d.ts +2 -1
  65. package/dist/static/components/slider.d.ts +2 -1
  66. package/dist/static/components/spinner.d.ts +2 -1
  67. package/dist/static/components/switchInput.d.ts +2 -1
  68. package/dist/static/components/table.d.ts +2 -1
  69. package/dist/static/components/tag.d.ts +2 -1
  70. package/dist/static/components/tagsInput.d.ts +2 -1
  71. package/dist/static/components/textarea.d.ts +2 -1
  72. package/dist/static/components/toolbar.d.ts +2 -1
  73. package/dist/static/components/tooltip.d.ts +2 -1
  74. package/dist/static/h.d.ts +2 -0
  75. package/dist/static/index.cjs.js +1 -1
  76. package/dist/static/index.d.ts +6 -0
  77. package/dist/static/index.es.js +366 -216
  78. package/dist/static/render.d.ts +2 -1
  79. package/dist/static/stringH.d.ts +2 -0
  80. package/dist/static/types.d.ts +5 -0
  81. package/dist/tailwind.css +222 -0
  82. package/dist/tokens.css +0 -223
  83. package/dist/types/corners.d.ts +1 -0
  84. package/dist/utils/slots.d.ts +6 -0
  85. package/llms-full.txt +17 -9
  86. package/package.json +9 -3
  87. package/src/components/Accordion/SkAccordion.vue +5 -2
  88. package/src/components/Accordion/SkAccordionItem.vue +7 -4
  89. package/src/components/Accordion/context.ts +23 -0
  90. package/src/components/Alert/SkAlert.vue +4 -2
  91. package/src/components/Autocomplete/SkAutocomplete.test.ts +83 -0
  92. package/src/components/Autocomplete/SkAutocomplete.vue +305 -0
  93. package/src/components/Autocomplete/SkAutocompleteEmpty.vue +39 -0
  94. package/src/components/Autocomplete/SkAutocompleteGroup.vue +46 -0
  95. package/src/components/Autocomplete/SkAutocompleteGroupLabel.vue +39 -0
  96. package/src/components/Autocomplete/SkAutocompleteItem.vue +85 -0
  97. package/src/components/Autocomplete/SkAutocompleteSeparator.vue +39 -0
  98. package/src/components/Autocomplete/index.ts +13 -0
  99. package/src/components/Autocomplete/types.ts +10 -0
  100. package/src/components/Breadcrumbs/SkBreadcrumbItem.vue +8 -3
  101. package/src/components/Breadcrumbs/SkBreadcrumbSeparator.vue +8 -2
  102. package/src/components/Breadcrumbs/SkBreadcrumbs.vue +11 -14
  103. package/src/components/Breadcrumbs/context.ts +20 -0
  104. package/src/components/Button/SkButton.vue +54 -11
  105. package/src/components/Button/types.ts +6 -0
  106. package/src/components/Card/SkCard.vue +12 -5
  107. package/src/components/Checkbox/SkCheckbox.vue +9 -2
  108. package/src/components/ColorPicker/SkColorPicker.vue +27 -5
  109. package/src/components/ContextMenu/SkContextMenu.vue +4 -1
  110. package/src/components/ContextMenu/SkContextMenuSubmenu.vue +5 -2
  111. package/src/components/ContextMenu/context.ts +17 -0
  112. package/src/components/Dropdown/SkDropdown.vue +2 -1
  113. package/src/components/Dropdown/SkDropdownSubmenu.vue +4 -3
  114. package/src/components/Dropdown/context.ts +16 -0
  115. package/src/components/Field/SkField.test.ts +88 -0
  116. package/src/components/Field/SkField.vue +15 -7
  117. package/src/components/Input/SkInput.test.ts +61 -0
  118. package/src/components/Input/SkInput.vue +42 -7
  119. package/src/components/Input/types.ts +2 -0
  120. package/src/components/InputGroup/SkInputGroup.test.ts +171 -0
  121. package/src/components/InputGroup/SkInputGroup.vue +131 -0
  122. package/src/components/InputGroup/SkInputGroupAddon.test.ts +104 -0
  123. package/src/components/InputGroup/SkInputGroupAddon.vue +107 -0
  124. package/src/components/InputGroup/types.ts +27 -0
  125. package/src/components/Listbox/SkListbox.vue +27 -6
  126. package/src/components/Modal/SkModal.vue +11 -4
  127. package/src/components/NavBar/SkNavBar.vue +5 -4
  128. package/src/components/NumberInput/SkNumberInput.vue +49 -8
  129. package/src/components/NumberInput/types.ts +2 -0
  130. package/src/components/Page/SkPage.vue +18 -15
  131. package/src/components/Pagination/SkPagination.vue +6 -3
  132. package/src/components/Pagination/SkPaginationItem.vue +8 -5
  133. package/src/components/Pagination/context.ts +19 -0
  134. package/src/components/Panel/types.ts +3 -2
  135. package/src/components/Popover/SkPopover.vue +11 -4
  136. package/src/components/Radio/SkRadio.vue +14 -4
  137. package/src/components/Radio/SkRadioGroup.vue +4 -2
  138. package/src/components/Radio/context.ts +17 -0
  139. package/src/components/Select/SkSelect.vue +39 -7
  140. package/src/components/Select/types.ts +2 -0
  141. package/src/components/Switch/SkSwitch.vue +14 -13
  142. package/src/components/Tabs/SkTab.vue +10 -3
  143. package/src/components/Tabs/SkTabList.vue +4 -2
  144. package/src/components/Tabs/SkTabs.vue +5 -3
  145. package/src/components/Tabs/context.ts +19 -0
  146. package/src/components/TagsInput/SkTagsInput.vue +28 -7
  147. package/src/components/Textarea/SkTextarea.vue +27 -6
  148. package/src/components/TreeView/SkTreeItem.vue +10 -2
  149. package/src/composables/injectionKeys.ts +52 -0
  150. package/src/index.ts +28 -0
  151. package/src/static/__tests__/parity.test.ts +2 -1
  152. package/src/static/__tests__/parityHarness.ts +5 -2
  153. package/src/static/components/__tests__/helpers.test.ts +191 -99
  154. package/src/static/components/alert.ts +12 -11
  155. package/src/static/components/avatar.ts +15 -16
  156. package/src/static/components/breadcrumbs.ts +3 -2
  157. package/src/static/components/button.ts +23 -27
  158. package/src/static/components/card.ts +3 -2
  159. package/src/static/components/checkbox.ts +11 -14
  160. package/src/static/components/colorPicker.ts +7 -9
  161. package/src/static/components/divider.ts +4 -3
  162. package/src/static/components/dropdown.ts +15 -6
  163. package/src/static/components/field.ts +32 -15
  164. package/src/static/components/group.ts +3 -2
  165. package/src/static/components/input.ts +20 -15
  166. package/src/static/components/inputGroup.ts +30 -0
  167. package/src/static/components/inputGroupAddon.ts +29 -0
  168. package/src/static/components/navBar.ts +30 -17
  169. package/src/static/components/numberInput.ts +17 -17
  170. package/src/static/components/page.ts +3 -2
  171. package/src/static/components/pagination.ts +3 -2
  172. package/src/static/components/panel.ts +3 -2
  173. package/src/static/components/progress.ts +3 -2
  174. package/src/static/components/radio.ts +14 -20
  175. package/src/static/components/select.ts +18 -15
  176. package/src/static/components/sidebar.ts +9 -13
  177. package/src/static/components/skeleton.ts +7 -10
  178. package/src/static/components/slider.ts +7 -9
  179. package/src/static/components/spinner.ts +22 -22
  180. package/src/static/components/switchInput.ts +12 -14
  181. package/src/static/components/table.ts +8 -10
  182. package/src/static/components/tag.ts +17 -11
  183. package/src/static/components/tagsInput.ts +3 -3
  184. package/src/static/components/textarea.ts +8 -13
  185. package/src/static/components/toolbar.ts +7 -10
  186. package/src/static/components/tooltip.ts +3 -2
  187. package/src/static/generated/defaults.ts +25 -9
  188. package/src/static/generated/propTypes.ts +19 -2
  189. package/src/static/h.ts +16 -0
  190. package/src/static/index.ts +8 -0
  191. package/src/static/render.test.ts +14 -10
  192. package/src/static/render.ts +33 -18
  193. package/src/static/specs.test.ts +1 -0
  194. package/src/static/specs.ts +22 -2
  195. package/src/static/stringH.ts +104 -0
  196. package/src/static/types.ts +25 -0
  197. package/src/styles/components/_autocomplete.scss +498 -0
  198. package/src/styles/components/_button.scss +55 -6
  199. package/src/styles/components/_index.scss +2 -0
  200. package/src/styles/components/_input-group.scss +292 -0
  201. package/src/styles/components/_input.scss +57 -9
  202. package/src/styles/components/_number-input.scss +88 -14
  203. package/src/styles/components/_select.scss +56 -9
  204. package/src/styles/mixins/_cut-border.scss +83 -0
  205. package/src/styles/tailwind.scss +262 -0
  206. package/src/styles/tokens.scss +8 -255
  207. package/src/types/corners.ts +10 -0
  208. package/src/utils/slots.test.ts +89 -0
  209. package/src/utils/slots.ts +80 -0
  210. package/web-types.json +392 -12
@@ -4,11 +4,11 @@
4
4
 
5
5
  <template>
6
6
  <div ref="rootRef" :class="classes" :style="customStyles" :data-scheme="theme">
7
- <header v-if="$slots.header" class="sk-page-header">
7
+ <header v-if="hasSlotContent(slots.header)" class="sk-page-header">
8
8
  <slot name="header" />
9
9
  </header>
10
10
 
11
- <div v-if="$slots.subheader" class="sk-page-subheader">
11
+ <div v-if="hasSlotContent(slots.subheader)" class="sk-page-subheader">
12
12
  <slot name="subheader" />
13
13
  </div>
14
14
 
@@ -18,25 +18,25 @@
18
18
  v-if="hasSidebar && !isSidebarDrawerActive"
19
19
  class="sk-page-sidebar"
20
20
  >
21
- <div v-if="$slots['sidebar-header']" class="sk-page-sidebar-header">
21
+ <div v-if="hasSlotContent(slots['sidebar-header'])" class="sk-page-sidebar-header">
22
22
  <slot name="sidebar-header" :is-drawer="false" />
23
23
  </div>
24
24
  <div class="sk-page-sidebar-body">
25
25
  <slot name="sidebar" :is-drawer="false" />
26
26
  </div>
27
- <div v-if="$slots['sidebar-footer']" class="sk-page-sidebar-footer">
27
+ <div v-if="hasSlotContent(slots['sidebar-footer'])" class="sk-page-sidebar-footer">
28
28
  <slot name="sidebar-footer" :is-drawer="false" />
29
29
  </div>
30
30
  </aside>
31
31
 
32
32
  <div class="sk-page-center">
33
- <div v-if="$slots['main-header']" class="sk-page-main-header">
33
+ <div v-if="hasSlotContent(slots['main-header'])" class="sk-page-main-header">
34
34
  <slot name="main-header" />
35
35
  </div>
36
36
  <main class="sk-page-content">
37
37
  <slot />
38
38
  </main>
39
- <div v-if="$slots['main-footer']" class="sk-page-main-footer">
39
+ <div v-if="hasSlotContent(slots['main-footer'])" class="sk-page-main-footer">
40
40
  <slot name="main-footer" />
41
41
  </div>
42
42
  </div>
@@ -46,19 +46,19 @@
46
46
  v-if="hasAside && !isAsideDrawerActive"
47
47
  class="sk-page-aside"
48
48
  >
49
- <div v-if="$slots['aside-header']" class="sk-page-aside-header">
49
+ <div v-if="hasSlotContent(slots['aside-header'])" class="sk-page-aside-header">
50
50
  <slot name="aside-header" :is-drawer="false" />
51
51
  </div>
52
52
  <div class="sk-page-aside-body">
53
53
  <slot name="aside" :is-drawer="false" />
54
54
  </div>
55
- <div v-if="$slots['aside-footer']" class="sk-page-aside-footer">
55
+ <div v-if="hasSlotContent(slots['aside-footer'])" class="sk-page-aside-footer">
56
56
  <slot name="aside-footer" :is-drawer="false" />
57
57
  </div>
58
58
  </aside>
59
59
  </div>
60
60
 
61
- <footer v-if="$slots.footer" class="sk-page-footer">
61
+ <footer v-if="hasSlotContent(slots.footer)" class="sk-page-footer">
62
62
  <slot name="footer" />
63
63
  </footer>
64
64
 
@@ -84,13 +84,13 @@
84
84
  tabindex="-1"
85
85
  @click="onSidebarDrawerClick"
86
86
  >
87
- <div v-if="$slots['sidebar-header']" class="sk-page-sidebar-header">
87
+ <div v-if="hasSlotContent(slots['sidebar-header'])" class="sk-page-sidebar-header">
88
88
  <slot name="sidebar-header" :is-drawer="true" />
89
89
  </div>
90
90
  <div class="sk-page-sidebar-body">
91
91
  <slot name="sidebar" :is-drawer="true" />
92
92
  </div>
93
- <div v-if="$slots['sidebar-footer']" class="sk-page-sidebar-footer">
93
+ <div v-if="hasSlotContent(slots['sidebar-footer'])" class="sk-page-sidebar-footer">
94
94
  <slot name="sidebar-footer" :is-drawer="true" />
95
95
  </div>
96
96
  </aside>
@@ -119,13 +119,13 @@
119
119
  tabindex="-1"
120
120
  @click="onAsideDrawerClick"
121
121
  >
122
- <div v-if="$slots['aside-header']" class="sk-page-aside-header">
122
+ <div v-if="hasSlotContent(slots['aside-header'])" class="sk-page-aside-header">
123
123
  <slot name="aside-header" :is-drawer="true" />
124
124
  </div>
125
125
  <div class="sk-page-aside-body">
126
126
  <slot name="aside" :is-drawer="true" />
127
127
  </div>
128
- <div v-if="$slots['aside-footer']" class="sk-page-aside-footer">
128
+ <div v-if="hasSlotContent(slots['aside-footer'])" class="sk-page-aside-footer">
129
129
  <slot name="aside-footer" :is-drawer="true" />
130
130
  </div>
131
131
  </aside>
@@ -199,6 +199,9 @@
199
199
  import { useFocusTrap } from '@/composables/useFocusTrap';
200
200
  import { providePageDrawers } from '@/composables/usePageDrawer';
201
201
 
202
+ // Utils
203
+ import { hasSlotContent } from '@/utils/slots';
204
+
202
205
  //------------------------------------------------------------------------------------------------------------------
203
206
 
204
207
  export interface SkPageComponentProps
@@ -332,8 +335,8 @@
332
335
  // Slot-derived state
333
336
  //------------------------------------------------------------------------------------------------------------------
334
337
 
335
- const hasSidebar = computed<boolean>(() => Boolean(slots.sidebar));
336
- const hasAside = computed<boolean>(() => Boolean(slots.aside));
338
+ const hasSidebar = computed<boolean>(() => hasSlotContent(slots.sidebar));
339
+ const hasAside = computed<boolean>(() => hasSlotContent(slots.aside));
337
340
 
338
341
  //------------------------------------------------------------------------------------------------------------------
339
342
  // Responsive mode detection — driven by SkPage's own width, not the viewport, so embedded
@@ -81,6 +81,9 @@
81
81
  import type { ComponentCustomColors } from '@/types';
82
82
  import type { SkPaginationProps } from './types';
83
83
 
84
+ // Context
85
+ import { PAGINATION_KIND_KEY, PAGINATION_SIZE_KEY, PAGINATION_VARIANT_KEY } from './context';
86
+
84
87
  //------------------------------------------------------------------------------------------------------------------
85
88
 
86
89
  export interface SkPaginationComponentProps extends SkPaginationProps, ComponentCustomColors
@@ -189,9 +192,9 @@
189
192
 
190
193
  //------------------------------------------------------------------------------------------------------------------
191
194
 
192
- provide('pagination-kind', toRef(() => props.kind));
193
- provide('pagination-size', toRef(() => props.size));
194
- provide('pagination-variant', toRef(() => props.variant));
195
+ provide(PAGINATION_KIND_KEY, toRef(() => props.kind));
196
+ provide(PAGINATION_SIZE_KEY, toRef(() => props.size));
197
+ provide(PAGINATION_VARIANT_KEY, toRef(() => props.variant));
195
198
 
196
199
  //------------------------------------------------------------------------------------------------------------------
197
200
 
@@ -39,10 +39,13 @@
39
39
  * ```
40
40
  */
41
41
 
42
- import { type Ref, computed, inject } from 'vue';
42
+ import { computed, inject } from 'vue';
43
43
 
44
44
  // Types
45
- import type { SkPaginationItemProps, SkPaginationKind, SkPaginationSize, SkPaginationVariant } from './types';
45
+ import type { SkPaginationItemProps } from './types';
46
+
47
+ // Context
48
+ import { PAGINATION_KIND_KEY, PAGINATION_SIZE_KEY, PAGINATION_VARIANT_KEY } from './context';
46
49
 
47
50
  //------------------------------------------------------------------------------------------------------------------
48
51
 
@@ -98,9 +101,9 @@
98
101
 
99
102
  //------------------------------------------------------------------------------------------------------------------
100
103
 
101
- const kindRef = inject<Ref<SkPaginationKind>>('pagination-kind');
102
- const sizeRef = inject<Ref<SkPaginationSize>>('pagination-size');
103
- const variantRef = inject<Ref<SkPaginationVariant>>('pagination-variant');
104
+ const kindRef = inject(PAGINATION_KIND_KEY, undefined);
105
+ const sizeRef = inject(PAGINATION_SIZE_KEY, undefined);
106
+ const variantRef = inject(PAGINATION_VARIANT_KEY, undefined);
104
107
 
105
108
  const kind = computed(() => kindRef?.value ?? 'neutral');
106
109
  const size = computed(() => sizeRef?.value ?? 'md');
@@ -0,0 +1,19 @@
1
+ //----------------------------------------------------------------------------------------------------------------------
2
+ // Pagination Context
3
+ //
4
+ // Injection keys for SkPaginationItem descendants to inherit kind, size, and variant from the
5
+ // surrounding SkPagination without manual wiring.
6
+ //----------------------------------------------------------------------------------------------------------------------
7
+
8
+ import type { InjectionKey, Ref } from 'vue';
9
+
10
+ import type { SkPaginationKind, SkPaginationSize, SkPaginationVariant } from './types';
11
+
12
+ //----------------------------------------------------------------------------------------------------------------------
13
+
14
+ export const PAGINATION_KIND_KEY : InjectionKey<Ref<SkPaginationKind | undefined>> = Symbol('sk-pagination-kind');
15
+ export const PAGINATION_SIZE_KEY : InjectionKey<Ref<SkPaginationSize | undefined>> = Symbol('sk-pagination-size');
16
+ export const PAGINATION_VARIANT_KEY : InjectionKey<Ref<SkPaginationVariant | undefined>>
17
+ = Symbol('sk-pagination-variant');
18
+
19
+ //----------------------------------------------------------------------------------------------------------------------
@@ -3,6 +3,7 @@
3
3
  //----------------------------------------------------------------------------------------------------------------------
4
4
 
5
5
  import type { ComponentKind } from '@/types';
6
+ import type { SkCorner } from '@/types/corners';
6
7
 
7
8
  //----------------------------------------------------------------------------------------------------------------------
8
9
 
@@ -12,7 +13,7 @@ export type SkPanelKind = ComponentKind;
12
13
  // Panel sizes (only affects cut size, not padding or dimensions)
13
14
  export type SkPanelSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl';
14
15
 
15
- // Which corners get the bevel cut
16
- export type SkPanelCorner = 'top-left' | 'top-right' | 'bottom-right' | 'bottom-left';
16
+ // Re-export under the legacy name so consumers and SkPanel continue to compile unchanged.
17
+ export type SkPanelCorner = SkCorner;
17
18
 
18
19
  //----------------------------------------------------------------------------------------------------------------------
@@ -14,7 +14,7 @@
14
14
  :collision-padding="8"
15
15
  >
16
16
  <!-- Header -->
17
- <div v-if="title || $slots.header" class="sk-popover-header">
17
+ <div v-if="title || hasSlotContent(slots.header)" class="sk-popover-header">
18
18
  <h3 v-if="title" class="sk-popover-title">
19
19
  {{ title }}
20
20
  </h3>
@@ -42,12 +42,12 @@
42
42
  </div>
43
43
 
44
44
  <!-- Content -->
45
- <div v-if="$slots.default" class="sk-popover-body">
45
+ <div v-if="hasSlotContent(slots.default)" class="sk-popover-body">
46
46
  <slot />
47
47
  </div>
48
48
 
49
49
  <!-- Footer -->
50
- <div v-if="$slots.footer" class="sk-popover-footer">
50
+ <div v-if="hasSlotContent(slots.footer)" class="sk-popover-footer">
51
51
  <slot name="footer" />
52
52
  </div>
53
53
 
@@ -100,7 +100,7 @@
100
100
  * button pairs or other closing actions.
101
101
  */
102
102
 
103
- import { computed, toRef } from 'vue';
103
+ import { type Slots, computed, toRef, useSlots } from 'vue';
104
104
  import {
105
105
  PopoverArrow,
106
106
  PopoverClose,
@@ -118,6 +118,9 @@
118
118
  import { useCustomColors } from '@/composables/useCustomColors';
119
119
  import { usePortalContext } from '@/composables/usePortalContext';
120
120
 
121
+ // Utils
122
+ import { hasSlotContent } from '@/utils/slots';
123
+
121
124
  //------------------------------------------------------------------------------------------------------------------
122
125
 
123
126
  export interface SkPopoverComponentProps extends ComponentCustomColors
@@ -223,6 +226,10 @@
223
226
 
224
227
  //------------------------------------------------------------------------------------------------------------------
225
228
 
229
+ const slots : Slots = useSlots();
230
+
231
+ //------------------------------------------------------------------------------------------------------------------
232
+
226
233
  const contentClasses = computed(() => ({
227
234
  'sk-popover-content': true,
228
235
  [`sk-${ props.kind }`]: true,
@@ -12,7 +12,7 @@
12
12
  >
13
13
  <RadioGroupIndicator class="sk-radio-indicator" />
14
14
  </RadioGroupItem>
15
- <span v-if="label || $slots.default" class="sk-radio-label">
15
+ <span v-if="label || hasSlotContent(slots.default)" class="sk-radio-label">
16
16
  <slot>{{ label }}</slot>
17
17
  </span>
18
18
  </label>
@@ -46,7 +46,7 @@
46
46
  * formatting, icons, or complex layouts alongside the radio button.
47
47
  */
48
48
 
49
- import { type ComputedRef, computed, inject, toRef } from 'vue';
49
+ import { computed, inject, toRef, useSlots } from 'vue';
50
50
  import { RadioGroupIndicator, RadioGroupItem } from 'reka-ui';
51
51
 
52
52
  // Types
@@ -56,6 +56,12 @@
56
56
  // Composables
57
57
  import { useCustomColors } from '@/composables/useCustomColors';
58
58
 
59
+ // Context
60
+ import { RADIO_KIND_KEY, RADIO_SIZE_KEY } from './context';
61
+
62
+ // Utils
63
+ import { hasSlotContent } from '@/utils/slots';
64
+
59
65
  //------------------------------------------------------------------------------------------------------------------
60
66
 
61
67
  export interface SkRadioComponentProps extends ComponentCustomColors
@@ -110,9 +116,13 @@
110
116
 
111
117
  //------------------------------------------------------------------------------------------------------------------
112
118
 
119
+ const slots = useSlots();
120
+
121
+ //------------------------------------------------------------------------------------------------------------------
122
+
113
123
  // Inject parent kind and size
114
- const parentKind = inject<ComputedRef<SkRadioKind | undefined>>('radio-kind', computed(() => undefined));
115
- const parentSize = inject<ComputedRef<SkRadioSize | undefined>>('radio-size', computed(() => undefined));
124
+ const parentKind = inject(RADIO_KIND_KEY, computed(() => undefined));
125
+ const parentSize = inject(RADIO_SIZE_KEY, computed(() => undefined));
116
126
 
117
127
  //------------------------------------------------------------------------------------------------------------------
118
128
 
@@ -49,6 +49,8 @@
49
49
  // Types
50
50
  import type { SkRadioGroupOrientation, SkRadioKind, SkRadioSize } from './types';
51
51
 
52
+ import { RADIO_KIND_KEY, RADIO_SIZE_KEY } from './context';
53
+
52
54
  //------------------------------------------------------------------------------------------------------------------
53
55
 
54
56
  export interface SkRadioGroupComponentProps
@@ -134,8 +136,8 @@
134
136
  //------------------------------------------------------------------------------------------------------------------
135
137
 
136
138
  // Provide kind and size to child radios
137
- provide('radio-kind', computed(() => props.kind));
138
- provide('radio-size', computed(() => props.size));
139
+ provide(RADIO_KIND_KEY, computed(() => props.kind));
140
+ provide(RADIO_SIZE_KEY, computed(() => props.size));
139
141
 
140
142
  //------------------------------------------------------------------------------------------------------------------
141
143
 
@@ -0,0 +1,17 @@
1
+ //----------------------------------------------------------------------------------------------------------------------
2
+ // Radio Context
3
+ //
4
+ // Injection keys for SkRadio descendants to inherit kind and size from the surrounding
5
+ // SkRadioGroup without manual wiring.
6
+ //----------------------------------------------------------------------------------------------------------------------
7
+
8
+ import type { ComputedRef, InjectionKey } from 'vue';
9
+
10
+ import type { SkRadioKind, SkRadioSize } from './types';
11
+
12
+ //----------------------------------------------------------------------------------------------------------------------
13
+
14
+ export const RADIO_KIND_KEY : InjectionKey<ComputedRef<SkRadioKind | undefined>> = Symbol('sk-radio-kind');
15
+ export const RADIO_SIZE_KEY : InjectionKey<ComputedRef<SkRadioSize | undefined>> = Symbol('sk-radio-size');
16
+
17
+ //----------------------------------------------------------------------------------------------------------------------
@@ -72,7 +72,7 @@
72
72
  * to create visual dividers between groups of options.
73
73
  */
74
74
 
75
- import { type ComputedRef, computed, inject, provide, reactive, toRef } from 'vue';
75
+ import { computed, inject, provide, reactive, toRef } from 'vue';
76
76
  import {
77
77
  SelectContent,
78
78
  SelectPortal,
@@ -84,9 +84,16 @@
84
84
 
85
85
  // Types
86
86
  import type { ComponentCustomColors } from '@/types';
87
- import type { SkSelectKind, SkSelectSize } from './types';
87
+ import type { SkSelectCorner, SkSelectKind, SkSelectSize } from './types';
88
88
 
89
89
  // Composables
90
+ import {
91
+ NO_KIND,
92
+ NO_SIZE,
93
+ inheritedKindKey,
94
+ inputGroupSizeKey,
95
+ validationKindKey,
96
+ } from '@/composables/injectionKeys';
90
97
  import { useCustomColors } from '@/composables/useCustomColors';
91
98
  import { usePortalContext } from '@/composables/usePortalContext';
92
99
 
@@ -124,15 +131,22 @@
124
131
  * @default false
125
132
  */
126
133
  disabled ?: boolean;
134
+
135
+ /**
136
+ * Which corners receive the beveled cut. Pass an empty array for square corners.
137
+ * @default undefined (renders as ['top-right'])
138
+ */
139
+ corners ?: SkSelectCorner[];
127
140
  }
128
141
 
129
142
  //------------------------------------------------------------------------------------------------------------------
130
143
 
131
144
  const props = withDefaults(defineProps<SkSelectComponentProps>(), {
132
145
  kind: undefined,
133
- size: 'md',
146
+ size: undefined,
134
147
  placeholder: 'Select...',
135
148
  disabled: false,
149
+ corners: undefined,
136
150
  });
137
151
 
138
152
  //------------------------------------------------------------------------------------------------------------------
@@ -148,8 +162,9 @@
148
162
  // Handle portal context (theme injection/re-provision for nested portal components)
149
163
  const { theme } = usePortalContext();
150
164
 
151
- // Inject field kind from parent SkField
152
- const fieldKind = inject<ComputedRef<SkSelectKind | undefined>>('field-kind', computed(() => undefined));
165
+ const validationKind = inject(validationKindKey, NO_KIND);
166
+ const inheritedKind = inject(inheritedKindKey, NO_KIND);
167
+ const inputGroupSize = inject(inputGroupSizeKey, NO_SIZE);
153
168
 
154
169
  //------------------------------------------------------------------------------------------------------------------
155
170
 
@@ -175,14 +190,31 @@
175
190
 
176
191
  //------------------------------------------------------------------------------------------------------------------
177
192
 
178
- const effectiveKind = computed(() => fieldKind.value || props.kind || 'neutral');
193
+ const effectiveKind = computed<SkSelectKind>(() =>
194
+ {
195
+ if(validationKind.value !== undefined) { return validationKind.value; }
196
+ if(props.kind !== undefined) { return props.kind; }
197
+ if(inheritedKind.value !== undefined) { return inheritedKind.value; }
198
+ return 'neutral';
199
+ });
200
+
201
+ const effectiveSize = computed<SkSelectSize>(() =>
202
+ {
203
+ if(props.size !== undefined) { return props.size; }
204
+ if(inputGroupSize.value !== undefined) { return inputGroupSize.value; }
205
+ return 'md';
206
+ });
179
207
 
180
208
  //------------------------------------------------------------------------------------------------------------------
181
209
 
182
210
  const wrapperClasses = computed(() => ({
183
211
  'sk-select': true,
184
212
  [`sk-${ effectiveKind.value }`]: true,
185
- [`sk-${ props.size }`]: true,
213
+ [`sk-${ effectiveSize.value }`]: true,
214
+ 'sk-cut-top-left': props.corners?.includes('top-left') ?? false,
215
+ 'sk-cut-top-right': props.corners?.includes('top-right') ?? false,
216
+ 'sk-cut-bottom-right': props.corners?.includes('bottom-right') ?? false,
217
+ 'sk-cut-bottom-left': props.corners?.includes('bottom-left') ?? false,
186
218
  }));
187
219
 
188
220
  //------------------------------------------------------------------------------------------------------------------
@@ -3,8 +3,10 @@
3
3
  //----------------------------------------------------------------------------------------------------------------------
4
4
 
5
5
  import type { ComponentKind, ComponentSize } from '@/types';
6
+ import type { SkCorner } from '@/types/corners';
6
7
 
7
8
  export type SkSelectKind = ComponentKind;
8
9
  export type SkSelectSize = ComponentSize;
10
+ export type SkSelectCorner = SkCorner;
9
11
 
10
12
  //----------------------------------------------------------------------------------------------------------------------
@@ -18,17 +18,17 @@
18
18
  </SwitchRoot>
19
19
  <label v-if="showLabel" class="sk-switch-label">
20
20
  <!-- Default slot overrides everything -->
21
- <slot v-if="slots.default" />
21
+ <slot v-if="hasSlotContent(slots.default)" />
22
22
  <!-- If using on/off labels with animation -->
23
23
  <Transition v-else-if="useOnOffLabels && !disableLabelAnimation" name="sk-switch-label-fade" mode="out-in">
24
24
  <span v-if="modelValue" :key="'on'">
25
- <slot v-if="slots['label-on']" name="label-on" />
25
+ <slot v-if="hasSlotContent(slots['label-on'])" name="label-on" />
26
26
  <template v-else>
27
27
  {{ labelOn }}
28
28
  </template>
29
29
  </span>
30
30
  <span v-else :key="'off'">
31
- <slot v-if="slots['label-off']" name="label-off" />
31
+ <slot v-if="hasSlotContent(slots['label-off'])" name="label-off" />
32
32
  <template v-else>
33
33
  {{ labelOff }}
34
34
  </template>
@@ -37,13 +37,13 @@
37
37
  <!-- If using on/off labels without animation -->
38
38
  <template v-else-if="useOnOffLabels && disableLabelAnimation">
39
39
  <span v-if="modelValue">
40
- <slot v-if="slots['label-on']" name="label-on" />
40
+ <slot v-if="hasSlotContent(slots['label-on'])" name="label-on" />
41
41
  <template v-else>
42
42
  {{ labelOn }}
43
43
  </template>
44
44
  </span>
45
45
  <span v-else>
46
- <slot v-if="slots['label-off']" name="label-off" />
46
+ <slot v-if="hasSlotContent(slots['label-off'])" name="label-off" />
47
47
  <template v-else>
48
48
  {{ labelOff }}
49
49
  </template>
@@ -88,6 +88,9 @@
88
88
  // Composables
89
89
  import { useCustomColors } from '@/composables/useCustomColors';
90
90
 
91
+ // Utils
92
+ import { hasSlotContent } from '@/utils/slots';
93
+
91
94
  //------------------------------------------------------------------------------------------------------------------
92
95
 
93
96
  export interface SkSwitchComponentProps extends ComponentCustomColors
@@ -232,14 +235,12 @@
232
235
  // - labelOn/labelOff props are provided, OR
233
236
  // - label-on/label-off slots are provided, OR
234
237
  // - fallback label prop is provided
235
- return Boolean(
236
- slots.default
237
- || props.labelOn
238
- || props.labelOff
239
- || slots['label-on']
240
- || slots['label-off']
241
- || props.label
242
- );
238
+ return hasSlotContent(slots.default)
239
+ || Boolean(props.labelOn)
240
+ || Boolean(props.labelOff)
241
+ || hasSlotContent(slots['label-on'])
242
+ || hasSlotContent(slots['label-off'])
243
+ || Boolean(props.label);
243
244
  });
244
245
 
245
246
  const useOnOffLabels = computed(() =>
@@ -8,7 +8,7 @@
8
8
  :disabled="disabled"
9
9
  :class="classes"
10
10
  >
11
- <span v-if="$slots.icon" class="sk-tab-icon">
11
+ <span v-if="hasSlotContent(slots.icon)" class="sk-tab-icon">
12
12
  <slot name="icon" />
13
13
  </span>
14
14
  <span class="sk-tab-label">
@@ -47,9 +47,12 @@
47
47
  * @slot icon - Optional icon displayed before the tab label. Useful for visual indicators.
48
48
  */
49
49
 
50
- import { type ComputedRef, computed, inject } from 'vue';
50
+ import { type Slots, computed, inject, useSlots } from 'vue';
51
51
  import { TabsTrigger } from 'reka-ui';
52
52
  import type { ComponentKind } from '@/types';
53
+ import { hasSlotContent } from '@/utils/slots';
54
+
55
+ import { TABS_KIND_KEY } from './context';
53
56
 
54
57
  //------------------------------------------------------------------------------------------------------------------
55
58
 
@@ -93,8 +96,12 @@
93
96
 
94
97
  //------------------------------------------------------------------------------------------------------------------
95
98
 
99
+ const slots : Slots = useSlots();
100
+
101
+ //------------------------------------------------------------------------------------------------------------------
102
+
96
103
  // Inject parent kind (Sleekspace-specific for theming)
97
- const parentKind = inject<ComputedRef<ComponentKind | undefined>>('tabs-kind', computed(() => undefined));
104
+ const parentKind = inject(TABS_KIND_KEY, computed(() => undefined));
98
105
 
99
106
  // Use prop kind if provided, otherwise use parent kind
100
107
  const kind = computed(() => props.kind ?? parentKind.value);
@@ -37,6 +37,8 @@
37
37
  import { TabsList } from 'reka-ui';
38
38
  import type { SkTabsOrientation } from './types.ts';
39
39
 
40
+ import { TABS_ORIENTATION_KEY } from './context';
41
+
40
42
  //------------------------------------------------------------------------------------------------------------------
41
43
 
42
44
  export interface SkTabListComponentProps
@@ -60,11 +62,11 @@
60
62
  // Inject orientation from parent (if prop not provided)
61
63
  // Note: RekaUI's TabsList gets orientation from TabsRoot context automatically,
62
64
  // but we need it for our styling classes
63
- const contextOrientation = inject<any>('tabs-orientation', 'horizontal');
65
+ const contextOrientation = inject(TABS_ORIENTATION_KEY, computed(() => 'horizontal' as const));
64
66
 
65
67
  //------------------------------------------------------------------------------------------------------------------
66
68
 
67
- const effectiveOrientation = computed(() => props.orientation || contextOrientation.value);
69
+ const effectiveOrientation = computed(() => props.orientation ?? contextOrientation.value);
68
70
 
69
71
  const classes = computed(() =>
70
72
  {
@@ -49,6 +49,8 @@
49
49
  import type { ComponentCustomColors, ComponentKind } from '@/types';
50
50
  import { useCustomColors } from '@/composables/useCustomColors';
51
51
 
52
+ import { TABS_KIND_KEY, TABS_ORIENTATION_KEY, TABS_PLACEMENT_KEY } from './context';
53
+
52
54
  //------------------------------------------------------------------------------------------------------------------
53
55
 
54
56
  export interface SkTabsComponentProps extends ComponentCustomColors
@@ -106,9 +108,9 @@
106
108
 
107
109
  // Provide our custom props to child components for styling
108
110
  // (RekaUI handles its own context internally, but we need these for our CSS classes)
109
- provide('tabs-orientation', computed(() => props.orientation));
110
- provide('tabs-placement', computed(() => props.placement));
111
- provide('tabs-kind', computed(() => props.kind));
111
+ provide(TABS_ORIENTATION_KEY, computed(() => props.orientation));
112
+ provide(TABS_PLACEMENT_KEY, computed(() => props.placement));
113
+ provide(TABS_KIND_KEY, computed(() => props.kind));
112
114
 
113
115
  //------------------------------------------------------------------------------------------------------------------
114
116
 
@@ -0,0 +1,19 @@
1
+ //----------------------------------------------------------------------------------------------------------------------
2
+ // Tabs Context
3
+ //
4
+ // Injection keys for SkTab / SkTabList descendants to inherit kind, orientation, and placement
5
+ // from the surrounding SkTabs without manual wiring.
6
+ //----------------------------------------------------------------------------------------------------------------------
7
+
8
+ import type { ComputedRef, InjectionKey } from 'vue';
9
+
10
+ import type { ComponentKind } from '@/types';
11
+ import type { SkTabsOrientation, SkTabsPlacement } from './types';
12
+
13
+ //----------------------------------------------------------------------------------------------------------------------
14
+
15
+ export const TABS_KIND_KEY : InjectionKey<ComputedRef<ComponentKind | undefined>> = Symbol('sk-tabs-kind');
16
+ export const TABS_ORIENTATION_KEY : InjectionKey<ComputedRef<SkTabsOrientation>> = Symbol('sk-tabs-orientation');
17
+ export const TABS_PLACEMENT_KEY : InjectionKey<ComputedRef<SkTabsPlacement>> = Symbol('sk-tabs-placement');
18
+
19
+ //----------------------------------------------------------------------------------------------------------------------