@skewedaspect/sleekspace-ui 0.2.0-beta.1

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 (266) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +111 -0
  3. package/dist/sleekspace-ui.css +12844 -0
  4. package/dist/sleekspace-ui.es.js +19021 -0
  5. package/dist/sleekspace-ui.umd.js +19040 -0
  6. package/docs/components/accordion.md +92 -0
  7. package/docs/components/alert.md +72 -0
  8. package/docs/components/avatar.md +69 -0
  9. package/docs/components/breadcrumbs.md +65 -0
  10. package/docs/components/button/_meta.yaml +12 -0
  11. package/docs/components/button/accessibility.md +16 -0
  12. package/docs/components/button/custom-colors.md +18 -0
  13. package/docs/components/button/icons.md +31 -0
  14. package/docs/components/button/intro.md +8 -0
  15. package/docs/components/button/kinds.md +25 -0
  16. package/docs/components/button/sizes.md +14 -0
  17. package/docs/components/button/states.md +12 -0
  18. package/docs/components/button/usage.md +23 -0
  19. package/docs/components/button/variants.md +14 -0
  20. package/docs/components/button.md +110 -0
  21. package/docs/components/card.md +87 -0
  22. package/docs/components/checkbox.md +77 -0
  23. package/docs/components/collapsible.md +71 -0
  24. package/docs/components/divider.md +62 -0
  25. package/docs/components/dropdown.md +88 -0
  26. package/docs/components/field.md +80 -0
  27. package/docs/components/group.md +41 -0
  28. package/docs/components/input.md +84 -0
  29. package/docs/components/listbox.md +82 -0
  30. package/docs/components/modal.md +101 -0
  31. package/docs/components/navbar.md +64 -0
  32. package/docs/components/number-input.md +78 -0
  33. package/docs/components/page.md +77 -0
  34. package/docs/components/pagination.md +88 -0
  35. package/docs/components/panel.md +74 -0
  36. package/docs/components/popover.md +93 -0
  37. package/docs/components/progress.md +76 -0
  38. package/docs/components/radio.md +86 -0
  39. package/docs/components/sidebar.md +74 -0
  40. package/docs/components/skeleton.md +76 -0
  41. package/docs/components/slider.md +94 -0
  42. package/docs/components/spinner.md +59 -0
  43. package/docs/components/switch.md +97 -0
  44. package/docs/components/table.md +91 -0
  45. package/docs/components/tabs.md +108 -0
  46. package/docs/components/tag.md +75 -0
  47. package/docs/components/tags-input.md +88 -0
  48. package/docs/components/textarea.md +80 -0
  49. package/docs/components/theme.md +65 -0
  50. package/docs/components/toast.md +95 -0
  51. package/docs/components/tooltip.md +90 -0
  52. package/docs/guides/custom-colors.md +84 -0
  53. package/docs/guides/design-tokens.md +105 -0
  54. package/docs/guides/getting-started.md +144 -0
  55. package/docs/guides/installation.md +62 -0
  56. package/docs/guides/theming.md +101 -0
  57. package/package.json +76 -0
  58. package/src/components/Accordion/SkAccordion.vue +133 -0
  59. package/src/components/Accordion/SkAccordionItem.vue +131 -0
  60. package/src/components/Accordion/index.ts +3 -0
  61. package/src/components/Accordion/types.ts +9 -0
  62. package/src/components/Alert/SkAlert.vue +137 -0
  63. package/src/components/Alert/types.ts +10 -0
  64. package/src/components/Avatar/SkAvatar.vue +141 -0
  65. package/src/components/Avatar/index.ts +8 -0
  66. package/src/components/Avatar/types.ts +31 -0
  67. package/src/components/Breadcrumbs/SkBreadcrumbItem.vue +76 -0
  68. package/src/components/Breadcrumbs/SkBreadcrumbSeparator.vue +38 -0
  69. package/src/components/Breadcrumbs/SkBreadcrumbs.vue +93 -0
  70. package/src/components/Breadcrumbs/index.ts +10 -0
  71. package/src/components/Breadcrumbs/types.ts +36 -0
  72. package/src/components/Button/SkButton.vue +148 -0
  73. package/src/components/Button/types.ts +21 -0
  74. package/src/components/Card/SkCard.vue +144 -0
  75. package/src/components/Card/types.ts +12 -0
  76. package/src/components/Checkbox/SkCheckbox.vue +136 -0
  77. package/src/components/Checkbox/index.ts +8 -0
  78. package/src/components/Checkbox/types.ts +10 -0
  79. package/src/components/Collapsible/SkCollapsible.vue +159 -0
  80. package/src/components/Collapsible/index.ts +2 -0
  81. package/src/components/Collapsible/types.ts +8 -0
  82. package/src/components/Divider/SkDivider.vue +63 -0
  83. package/src/components/Divider/types.ts +15 -0
  84. package/src/components/Dropdown/SkDropdown.vue +150 -0
  85. package/src/components/Dropdown/SkDropdownMenuItem.vue +58 -0
  86. package/src/components/Dropdown/SkDropdownMenuSeparator.vue +26 -0
  87. package/src/components/Dropdown/SkDropdownSubmenu.vue +107 -0
  88. package/src/components/Dropdown/index.ts +11 -0
  89. package/src/components/Dropdown/types.ts +11 -0
  90. package/src/components/Field/SkField.vue +152 -0
  91. package/src/components/Field/index.ts +8 -0
  92. package/src/components/Field/types.ts +7 -0
  93. package/src/components/Group/SkGroup.vue +52 -0
  94. package/src/components/Group/types.ts +10 -0
  95. package/src/components/Input/SkInput.vue +117 -0
  96. package/src/components/Input/index.ts +8 -0
  97. package/src/components/Input/types.ts +11 -0
  98. package/src/components/Listbox/SkListbox.vue +164 -0
  99. package/src/components/Listbox/SkListboxItem.vue +68 -0
  100. package/src/components/Listbox/SkListboxSeparator.vue +26 -0
  101. package/src/components/Listbox/index.ts +10 -0
  102. package/src/components/Listbox/types.ts +10 -0
  103. package/src/components/Modal/SkModal.vue +231 -0
  104. package/src/components/Modal/index.ts +8 -0
  105. package/src/components/Modal/types.ts +12 -0
  106. package/src/components/NavBar/SkNavBar.vue +83 -0
  107. package/src/components/NavBar/index.ts +8 -0
  108. package/src/components/NavBar/types.ts +15 -0
  109. package/src/components/NumberInput/SkNumberInput.vue +168 -0
  110. package/src/components/NumberInput/index.ts +8 -0
  111. package/src/components/NumberInput/types.ts +10 -0
  112. package/src/components/Page/SkPage.vue +94 -0
  113. package/src/components/Page/index.ts +8 -0
  114. package/src/components/Page/types.ts +21 -0
  115. package/src/components/Pagination/SkPagination.vue +185 -0
  116. package/src/components/Pagination/SkPaginationItem.vue +107 -0
  117. package/src/components/Pagination/index.ts +9 -0
  118. package/src/components/Pagination/types.ts +40 -0
  119. package/src/components/Panel/SkPanel.vue +96 -0
  120. package/src/components/Panel/types.ts +15 -0
  121. package/src/components/Popover/SkPopover.vue +185 -0
  122. package/src/components/Popover/index.ts +8 -0
  123. package/src/components/Popover/types.ts +11 -0
  124. package/src/components/Progress/SkProgress.vue +144 -0
  125. package/src/components/Progress/index.ts +8 -0
  126. package/src/components/Progress/types.ts +34 -0
  127. package/src/components/Radio/SkRadio.vue +110 -0
  128. package/src/components/Radio/SkRadioGroup.vue +92 -0
  129. package/src/components/Radio/index.ts +9 -0
  130. package/src/components/Radio/types.ts +11 -0
  131. package/src/components/Sidebar/README.md +405 -0
  132. package/src/components/Sidebar/SkSidebar.vue +88 -0
  133. package/src/components/Sidebar/SkSidebarItem.vue +58 -0
  134. package/src/components/Sidebar/SkSidebarSection.vue +40 -0
  135. package/src/components/Sidebar/types.ts +3 -0
  136. package/src/components/Skeleton/SkSkeleton.vue +171 -0
  137. package/src/components/Skeleton/index.ts +8 -0
  138. package/src/components/Skeleton/types.ts +31 -0
  139. package/src/components/Slider/SkSlider.vue +165 -0
  140. package/src/components/Slider/index.ts +8 -0
  141. package/src/components/Slider/types.ts +44 -0
  142. package/src/components/Spinner/SkSpinner.vue +105 -0
  143. package/src/components/Spinner/index.ts +8 -0
  144. package/src/components/Spinner/types.ts +28 -0
  145. package/src/components/Switch/SkSwitch.vue +215 -0
  146. package/src/components/Switch/index.ts +8 -0
  147. package/src/components/Switch/types.ts +12 -0
  148. package/src/components/Table/SkTable.vue +109 -0
  149. package/src/components/Table/index.ts +2 -0
  150. package/src/components/Table/types.ts +15 -0
  151. package/src/components/Tabs/README.md +331 -0
  152. package/src/components/Tabs/SkTab.vue +84 -0
  153. package/src/components/Tabs/SkTabList.vue +62 -0
  154. package/src/components/Tabs/SkTabPanel.vue +47 -0
  155. package/src/components/Tabs/SkTabPanels.vue +23 -0
  156. package/src/components/Tabs/SkTabs.vue +124 -0
  157. package/src/components/Tabs/types.ts +21 -0
  158. package/src/components/Tag/SkTag.vue +129 -0
  159. package/src/components/Tag/types.ts +15 -0
  160. package/src/components/TagsInput/SkTagsInput.vue +184 -0
  161. package/src/components/TagsInput/index.ts +8 -0
  162. package/src/components/TagsInput/types.ts +10 -0
  163. package/src/components/Textarea/SkTextarea.vue +117 -0
  164. package/src/components/Textarea/index.ts +8 -0
  165. package/src/components/Textarea/types.ts +10 -0
  166. package/src/components/Theme/SkTheme.vue +47 -0
  167. package/src/components/Theme/types.ts +17 -0
  168. package/src/components/Theme/useTheme.ts +131 -0
  169. package/src/components/Toast/SkToast.vue +156 -0
  170. package/src/components/Toast/SkToastProvider.vue +180 -0
  171. package/src/components/Toast/index.ts +15 -0
  172. package/src/components/Toast/types.ts +63 -0
  173. package/src/components/Toast/useToast.ts +78 -0
  174. package/src/components/Tooltip/SkTooltip.vue +162 -0
  175. package/src/components/Tooltip/SkTooltipProvider.vue +114 -0
  176. package/src/components/Tooltip/index.ts +9 -0
  177. package/src/components/Tooltip/types.ts +13 -0
  178. package/src/composables/useCustomColors.test.ts +505 -0
  179. package/src/composables/useCustomColors.ts +124 -0
  180. package/src/composables/usePortalContext.test.ts +402 -0
  181. package/src/composables/usePortalContext.ts +95 -0
  182. package/src/global.d.ts +76 -0
  183. package/src/index.ts +259 -0
  184. package/src/styles/_scrollbar.scss +100 -0
  185. package/src/styles/base/_fonts.scss +105 -0
  186. package/src/styles/base/_global.scss +47 -0
  187. package/src/styles/base/_index.scss +24 -0
  188. package/src/styles/base/_reset.scss +11 -0
  189. package/src/styles/base/_typography.scss +178 -0
  190. package/src/styles/components/_accordion.scss +250 -0
  191. package/src/styles/components/_alert.scss +239 -0
  192. package/src/styles/components/_avatar.scss +133 -0
  193. package/src/styles/components/_breadcrumbs.scss +137 -0
  194. package/src/styles/components/_button.scss +731 -0
  195. package/src/styles/components/_card.scss +141 -0
  196. package/src/styles/components/_checkbox.scss +232 -0
  197. package/src/styles/components/_collapsible.scss +158 -0
  198. package/src/styles/components/_divider.scss +121 -0
  199. package/src/styles/components/_field.scss +87 -0
  200. package/src/styles/components/_group.scss +138 -0
  201. package/src/styles/components/_index.scss +46 -0
  202. package/src/styles/components/_input.scss +205 -0
  203. package/src/styles/components/_listbox.scss +453 -0
  204. package/src/styles/components/_menu.scss +216 -0
  205. package/src/styles/components/_modal.scss +329 -0
  206. package/src/styles/components/_navbar.scss +258 -0
  207. package/src/styles/components/_number-input.scss +352 -0
  208. package/src/styles/components/_page.scss +98 -0
  209. package/src/styles/components/_pagination.scss +411 -0
  210. package/src/styles/components/_panel.scss +281 -0
  211. package/src/styles/components/_popover.scss +258 -0
  212. package/src/styles/components/_progress.scss +280 -0
  213. package/src/styles/components/_radio.scss +255 -0
  214. package/src/styles/components/_sidebar.scss +92 -0
  215. package/src/styles/components/_skeleton.scss +138 -0
  216. package/src/styles/components/_slider.scss +262 -0
  217. package/src/styles/components/_spinner.scss +331 -0
  218. package/src/styles/components/_switch.scss +370 -0
  219. package/src/styles/components/_table.scss +405 -0
  220. package/src/styles/components/_tabs.scss +486 -0
  221. package/src/styles/components/_tag.scss +425 -0
  222. package/src/styles/components/_tags-input.scss +279 -0
  223. package/src/styles/components/_textarea.scss +208 -0
  224. package/src/styles/components/_toast.scss +331 -0
  225. package/src/styles/components/_tooltip.scss +206 -0
  226. package/src/styles/fonts/Titillium_Web/OFL.txt +93 -0
  227. package/src/styles/fonts/Titillium_Web/TitilliumWeb-Black.ttf +0 -0
  228. package/src/styles/fonts/Titillium_Web/TitilliumWeb-Bold.ttf +0 -0
  229. package/src/styles/fonts/Titillium_Web/TitilliumWeb-BoldItalic.ttf +0 -0
  230. package/src/styles/fonts/Titillium_Web/TitilliumWeb-ExtraLight.ttf +0 -0
  231. package/src/styles/fonts/Titillium_Web/TitilliumWeb-ExtraLightItalic.ttf +0 -0
  232. package/src/styles/fonts/Titillium_Web/TitilliumWeb-Italic.ttf +0 -0
  233. package/src/styles/fonts/Titillium_Web/TitilliumWeb-Light.ttf +0 -0
  234. package/src/styles/fonts/Titillium_Web/TitilliumWeb-LightItalic.ttf +0 -0
  235. package/src/styles/fonts/Titillium_Web/TitilliumWeb-Regular.ttf +0 -0
  236. package/src/styles/fonts/Titillium_Web/TitilliumWeb-SemiBold.ttf +0 -0
  237. package/src/styles/fonts/Titillium_Web/TitilliumWeb-SemiBoldItalic.ttf +0 -0
  238. package/src/styles/index.scss +17 -0
  239. package/src/styles/mixins/_cut-border.scss +254 -0
  240. package/src/styles/mixins/_index.scss +7 -0
  241. package/src/styles/theme/_variables.scss +42 -0
  242. package/src/styles/themes/README.md +127 -0
  243. package/src/styles/themes/_colorful.scss +58 -0
  244. package/src/styles/themes/_greyscale.scss +58 -0
  245. package/src/styles/themes/index.scss +9 -0
  246. package/src/styles/tokens/README.md +268 -0
  247. package/src/styles/tokens/_foundation-borders.scss +26 -0
  248. package/src/styles/tokens/_foundation-colors.scss +169 -0
  249. package/src/styles/tokens/_foundation-glow.scss +36 -0
  250. package/src/styles/tokens/_foundation-radius.scss +53 -0
  251. package/src/styles/tokens/_foundation-scrollbar.scss +31 -0
  252. package/src/styles/tokens/_foundation-shadows.scss +37 -0
  253. package/src/styles/tokens/_foundation-space.scss +36 -0
  254. package/src/styles/tokens/_foundation-transitions.scss +37 -0
  255. package/src/styles/tokens/_foundation-typography.scss +58 -0
  256. package/src/styles/tokens/_semantic-color-kinds.scss +112 -0
  257. package/src/styles/tokens/_semantic-colors.scss +10 -0
  258. package/src/styles/tokens/_semantic-interactive.scss +29 -0
  259. package/src/styles/tokens/_semantic-scrollbar.scss +48 -0
  260. package/src/styles/tokens/_semantic-surfaces.scss +36 -0
  261. package/src/styles/tokens/index.scss +38 -0
  262. package/src/styles/tokens.scss +268 -0
  263. package/src/styles/utilities/_index.scss +9 -0
  264. package/src/styles/utilities/_typography.scss +121 -0
  265. package/src/types.ts +50 -0
  266. package/web-types.json +3524 -0
@@ -0,0 +1,12 @@
1
+ //----------------------------------------------------------------------------------------------------------------------
2
+ // Modal Component Types
3
+ //----------------------------------------------------------------------------------------------------------------------
4
+
5
+ import type { ComponentKind, ComponentSize } from '@/types';
6
+
7
+ //----------------------------------------------------------------------------------------------------------------------
8
+
9
+ export type SkModalKind = ComponentKind;
10
+ export type SkModalSize = ComponentSize;
11
+
12
+ //----------------------------------------------------------------------------------------------------------------------
@@ -0,0 +1,83 @@
1
+ <!----------------------------------------------------------------------------------------------------------------------
2
+ - NavBar Component
3
+ --------------------------------------------------------------------------------------------------------------------->
4
+
5
+ <template>
6
+ <nav :class="classes" :style="customColorStyles">
7
+ <div class="sk-navbar-content">
8
+ <div v-if="slots.brand" class="sk-navbar-brand">
9
+ <slot name="brand" />
10
+ </div>
11
+
12
+ <div v-if="slots.default" class="sk-navbar-nav">
13
+ <slot />
14
+ </div>
15
+
16
+ <div v-if="slots.actions" class="sk-navbar-actions">
17
+ <slot name="actions" />
18
+ </div>
19
+ </div>
20
+ </nav>
21
+ </template>
22
+
23
+ <!--------------------------------------------------------------------------------------------------------------------->
24
+
25
+ <script setup lang="ts">
26
+ /**
27
+ * @component
28
+ * A navigation bar component for site-wide navigation with brand, nav items, and action slots.
29
+ * Supports sticky positioning and semantic color theming.
30
+ */
31
+
32
+ import { computed, toRef, useSlots } from 'vue';
33
+ import type { SkNavBarKind } from './types';
34
+ import type { ComponentCustomColors } from '@/types';
35
+ import { useCustomColors } from '@/composables/useCustomColors';
36
+
37
+ //------------------------------------------------------------------------------------------------------------------
38
+
39
+ /**
40
+ * A navigation bar component for site-wide navigation with brand, nav items, and action slots.
41
+ * Supports sticky positioning and semantic color theming.
42
+ */
43
+ export interface SkNavBarComponentProps extends ComponentCustomColors
44
+ {
45
+ /** Semantic color kind for the navbar */
46
+ kind ?: SkNavBarKind;
47
+ /** Whether the navbar sticks to the top of the viewport when scrolling */
48
+ sticky ?: boolean;
49
+ }
50
+
51
+ //------------------------------------------------------------------------------------------------------------------
52
+
53
+ const props = withDefaults(defineProps<SkNavBarComponentProps>(), {
54
+ kind: 'neutral',
55
+ sticky: true,
56
+ });
57
+
58
+ //------------------------------------------------------------------------------------------------------------------
59
+
60
+ const slots = useSlots();
61
+
62
+ //------------------------------------------------------------------------------------------------------------------
63
+
64
+ const classes = computed(() =>
65
+ {
66
+ return {
67
+ 'sk-navbar': true,
68
+ [`sk-${ props.kind }`]: true,
69
+ 'sk-sticky': props.sticky,
70
+ };
71
+ });
72
+
73
+ //------------------------------------------------------------------------------------------------------------------
74
+
75
+ // Custom color styles
76
+ const customColorStyles = useCustomColors(
77
+ 'navbar',
78
+ toRef(() => props.baseColor),
79
+ toRef(() => props.textColor)
80
+ );
81
+ </script>
82
+
83
+ <!--------------------------------------------------------------------------------------------------------------------->
@@ -0,0 +1,8 @@
1
+ //----------------------------------------------------------------------------------------------------------------------
2
+ // NavBar Component Exports
3
+ //----------------------------------------------------------------------------------------------------------------------
4
+
5
+ export { default as SkNavBar } from './SkNavBar.vue';
6
+ export * from './types';
7
+
8
+ //----------------------------------------------------------------------------------------------------------------------
@@ -0,0 +1,15 @@
1
+ //----------------------------------------------------------------------------------------------------------------------
2
+ // NavBar Types
3
+ //----------------------------------------------------------------------------------------------------------------------
4
+
5
+ import type { ComponentKind } from '@/types';
6
+
7
+ //----------------------------------------------------------------------------------------------------------------------
8
+
9
+ /**
10
+ * Available kinds for the navbar component.
11
+ * Supports both semantic kinds (themeable) and color kinds (direct palette access).
12
+ */
13
+ export type SkNavBarKind = ComponentKind;
14
+
15
+ //----------------------------------------------------------------------------------------------------------------------
@@ -0,0 +1,168 @@
1
+ <!----------------------------------------------------------------------------------------------------------------------
2
+ - NumberInput Component
3
+ --------------------------------------------------------------------------------------------------------------------->
4
+
5
+ <template>
6
+ <div :class="wrapperClasses">
7
+ <NumberFieldRoot
8
+ v-model="modelValue"
9
+ :class="classes"
10
+ :style="customColorStyles"
11
+ :disabled="disabled"
12
+ :readonly="readonly"
13
+ :required="required"
14
+ :name="name"
15
+ :min="min"
16
+ :max="max"
17
+ :step="step"
18
+ >
19
+ <NumberFieldInput :class="inputClasses" :placeholder="placeholder" />
20
+ <div class="sk-number-input-steppers">
21
+ <NumberFieldIncrement class="sk-number-input-increment">
22
+ <svg
23
+ xmlns="http://www.w3.org/2000/svg"
24
+ viewBox="0 0 24 24"
25
+ fill="none"
26
+ stroke="currentColor"
27
+ stroke-width="2"
28
+ stroke-linecap="square"
29
+ stroke-linejoin="miter"
30
+ >
31
+ <polyline points="18 15 12 9 6 15" />
32
+ </svg>
33
+ </NumberFieldIncrement>
34
+ <NumberFieldDecrement class="sk-number-input-decrement">
35
+ <svg
36
+ xmlns="http://www.w3.org/2000/svg"
37
+ viewBox="0 0 24 24"
38
+ fill="none"
39
+ stroke="currentColor"
40
+ stroke-width="2"
41
+ stroke-linecap="square"
42
+ stroke-linejoin="miter"
43
+ >
44
+ <polyline points="18 9 12 15 6 9" />
45
+ </svg>
46
+ </NumberFieldDecrement>
47
+ </div>
48
+ </NumberFieldRoot>
49
+ </div>
50
+ </template>
51
+
52
+ <!--------------------------------------------------------------------------------------------------------------------->
53
+
54
+ <style lang="scss" scoped>
55
+ // Component styles are implemented in /src/styles/components/_number-input.scss
56
+ </style>
57
+
58
+ <!--------------------------------------------------------------------------------------------------------------------->
59
+
60
+ <script setup lang="ts">
61
+ /**
62
+ * @component
63
+ * A numeric input component with stepper buttons powered by RekaUI.
64
+ * Supports keyboard navigation, min/max values, and step increments.
65
+ */
66
+
67
+ import { type ComputedRef, computed, inject, toRef } from 'vue';
68
+ import {
69
+ NumberFieldDecrement,
70
+ NumberFieldIncrement,
71
+ NumberFieldInput,
72
+ NumberFieldRoot,
73
+ } from 'reka-ui';
74
+
75
+ // Types
76
+ import type { ComponentCustomColors } from '@/types';
77
+ import type { SkNumberInputKind, SkNumberInputSize } from './types';
78
+
79
+ // Composables
80
+ import { useCustomColors } from '@/composables/useCustomColors';
81
+
82
+ //------------------------------------------------------------------------------------------------------------------
83
+
84
+ /**
85
+ * A numeric input component with stepper buttons powered by RekaUI.
86
+ */
87
+ export interface SkNumberInputComponentProps extends ComponentCustomColors
88
+ {
89
+ /** Semantic color kind (useful for validation states) */
90
+ kind ?: SkNumberInputKind;
91
+ /** Input size */
92
+ size ?: SkNumberInputSize;
93
+ /** Placeholder text */
94
+ placeholder ?: string;
95
+ /** Disabled state */
96
+ disabled ?: boolean;
97
+ /** Read-only state */
98
+ readonly ?: boolean;
99
+ /** Required for form validation */
100
+ required ?: boolean;
101
+ /** Form field name */
102
+ name ?: string;
103
+ /** Minimum value */
104
+ min ?: number;
105
+ /** Maximum value */
106
+ max ?: number;
107
+ /** Step increment/decrement amount */
108
+ step ?: number;
109
+ }
110
+
111
+ //------------------------------------------------------------------------------------------------------------------
112
+
113
+ const props = withDefaults(defineProps<SkNumberInputComponentProps>(), {
114
+ kind: undefined,
115
+ size: 'md',
116
+ placeholder: undefined,
117
+ disabled: false,
118
+ readonly: false,
119
+ required: false,
120
+ name: undefined,
121
+ min: undefined,
122
+ max: undefined,
123
+ step: 1,
124
+ });
125
+
126
+ //------------------------------------------------------------------------------------------------------------------
127
+
128
+ const modelValue = defineModel<number>({ default: 0 });
129
+
130
+ //------------------------------------------------------------------------------------------------------------------
131
+
132
+ // Inject kind from parent SkField if available
133
+ const fieldKind = inject<ComputedRef<SkNumberInputKind | undefined>>('field-kind', computed(() => undefined));
134
+
135
+ //------------------------------------------------------------------------------------------------------------------
136
+
137
+ const effectiveKind = computed(() => fieldKind.value || props.kind || 'neutral');
138
+
139
+ //------------------------------------------------------------------------------------------------------------------
140
+
141
+ const wrapperClasses = computed(() => ({
142
+ 'sk-number-input-wrapper': true,
143
+ [`sk-${ effectiveKind.value }`]: true,
144
+ [`sk-${ props.size }`]: true,
145
+ }));
146
+
147
+ //------------------------------------------------------------------------------------------------------------------
148
+
149
+ const classes = computed(() => ({
150
+ 'sk-number-input': true,
151
+ }));
152
+
153
+ //------------------------------------------------------------------------------------------------------------------
154
+
155
+ const inputClasses = computed(() => ({
156
+ 'sk-number-input-field': true,
157
+ }));
158
+
159
+ //------------------------------------------------------------------------------------------------------------------
160
+
161
+ const customColorStyles = useCustomColors(
162
+ 'number-input',
163
+ toRef(() => props.baseColor),
164
+ toRef(() => props.textColor)
165
+ );
166
+ </script>
167
+
168
+ <!--------------------------------------------------------------------------------------------------------------------->
@@ -0,0 +1,8 @@
1
+ //----------------------------------------------------------------------------------------------------------------------
2
+ // NumberInput Component Exports
3
+ //----------------------------------------------------------------------------------------------------------------------
4
+
5
+ export { default as SkNumberInput } from './SkNumberInput.vue';
6
+ export type { SkNumberInputKind, SkNumberInputSize } from './types';
7
+
8
+ //----------------------------------------------------------------------------------------------------------------------
@@ -0,0 +1,10 @@
1
+ //----------------------------------------------------------------------------------------------------------------------
2
+ // NumberInput Component Types
3
+ //----------------------------------------------------------------------------------------------------------------------
4
+
5
+ import type { ComponentKind, ComponentSize } from '@/types';
6
+
7
+ export type SkNumberInputKind = ComponentKind;
8
+ export type SkNumberInputSize = ComponentSize;
9
+
10
+ //----------------------------------------------------------------------------------------------------------------------
@@ -0,0 +1,94 @@
1
+ <template>
2
+ <div :class="classes" :style="customStyles">
3
+ <header v-if="$slots.header" class="sk-page-header">
4
+ <slot name="header" />
5
+ </header>
6
+
7
+ <div class="sk-page-main">
8
+ <aside v-if="$slots.sidebar" class="sk-page-sidebar">
9
+ <slot name="sidebar" />
10
+ </aside>
11
+
12
+ <main class="sk-page-content">
13
+ <slot />
14
+ </main>
15
+ </div>
16
+
17
+ <footer v-if="$slots.footer" class="sk-page-footer">
18
+ <slot name="footer" />
19
+ </footer>
20
+ </div>
21
+ </template>
22
+
23
+ <!--------------------------------------------------------------------------------------------------------------------->
24
+
25
+ <style lang="scss" scoped>
26
+ // Component styles are implemented in /src/styles/components/_page.scss
27
+ </style>
28
+
29
+ <!--------------------------------------------------------------------------------------------------------------------->
30
+
31
+ <script setup lang="ts">
32
+ /**
33
+ * @component SkPage
34
+ * A full-page layout component with header, sidebar, content, and footer slots.
35
+ * Provides a standard page structure with optional fixed header/footer and configurable sidebar.
36
+ */
37
+
38
+ import { computed } from 'vue';
39
+
40
+ // Types
41
+ import type { SkPageSidebarPosition } from './types';
42
+
43
+ //------------------------------------------------------------------------------------------------------------------
44
+
45
+ export interface SkPageComponentProps
46
+ {
47
+ /** Sidebar position */
48
+ sidebarPosition ?: SkPageSidebarPosition;
49
+ /** Fixed header (stays at top when scrolling) */
50
+ fixedHeader ?: boolean;
51
+ /** Fixed footer (stays at bottom when scrolling) */
52
+ fixedFooter ?: boolean;
53
+ /** Custom sidebar width */
54
+ sidebarWidth ?: string;
55
+ }
56
+
57
+ //------------------------------------------------------------------------------------------------------------------
58
+
59
+ const props = withDefaults(defineProps<SkPageComponentProps>(), {
60
+ sidebarPosition: 'left',
61
+ fixedHeader: false,
62
+ fixedFooter: false,
63
+ sidebarWidth: undefined,
64
+ });
65
+
66
+ //------------------------------------------------------------------------------------------------------------------
67
+ // Classes
68
+ //------------------------------------------------------------------------------------------------------------------
69
+
70
+ const classes = computed(() => ({
71
+ 'sk-page': true,
72
+ [`sk-sidebar-${ props.sidebarPosition }`]: true,
73
+ 'sk-fixed-header': props.fixedHeader,
74
+ 'sk-fixed-footer': props.fixedFooter,
75
+ }));
76
+
77
+ //------------------------------------------------------------------------------------------------------------------
78
+ // Custom Styles
79
+ //------------------------------------------------------------------------------------------------------------------
80
+
81
+ const customStyles = computed(() =>
82
+ {
83
+ if(!props.sidebarWidth)
84
+ {
85
+ return {};
86
+ }
87
+
88
+ return {
89
+ '--sk-page-sidebar-width': props.sidebarWidth,
90
+ };
91
+ });
92
+ </script>
93
+
94
+ <!--------------------------------------------------------------------------------------------------------------------->
@@ -0,0 +1,8 @@
1
+ //----------------------------------------------------------------------------------------------------------------------
2
+ // Page Component
3
+ //----------------------------------------------------------------------------------------------------------------------
4
+
5
+ export { default as SkPage } from './SkPage.vue';
6
+ export * from './types';
7
+
8
+ //----------------------------------------------------------------------------------------------------------------------
@@ -0,0 +1,21 @@
1
+ //----------------------------------------------------------------------------------------------------------------------
2
+ // Page Types
3
+ //----------------------------------------------------------------------------------------------------------------------
4
+
5
+ /** Sidebar position */
6
+ export type SkPageSidebarPosition = 'left' | 'right';
7
+
8
+ /** Page props interface */
9
+ export interface SkPageProps
10
+ {
11
+ /** Sidebar position */
12
+ sidebarPosition ?: SkPageSidebarPosition;
13
+ /** Fixed header (stays at top when scrolling) */
14
+ fixedHeader ?: boolean;
15
+ /** Fixed footer (stays at bottom when scrolling) */
16
+ fixedFooter ?: boolean;
17
+ /** Custom sidebar width */
18
+ sidebarWidth ?: string;
19
+ }
20
+
21
+ //----------------------------------------------------------------------------------------------------------------------
@@ -0,0 +1,185 @@
1
+ <template>
2
+ <nav :class="classes" :style="customColorStyles" aria-label="Pagination">
3
+ <SkPaginationItem
4
+ v-if="showFirstLast"
5
+ type="first"
6
+ :page="1"
7
+ :disabled="disabled || currentPage === 1"
8
+ @click="goToPage"
9
+ />
10
+
11
+ <SkPaginationItem
12
+ v-if="showPrevNext"
13
+ type="prev"
14
+ :page="currentPage - 1"
15
+ :disabled="disabled || currentPage === 1"
16
+ @click="goToPage"
17
+ />
18
+
19
+ <SkPaginationItem
20
+ v-for="(item, index) in paginationRange"
21
+ :key="index"
22
+ :type="typeof item === 'string' ? 'ellipsis' : 'page'"
23
+ :page="typeof item === 'number' ? item : undefined"
24
+ :active="typeof item === 'number' && item === currentPage"
25
+ :disabled="disabled"
26
+ @click="goToPage"
27
+ />
28
+
29
+ <SkPaginationItem
30
+ v-if="showPrevNext"
31
+ type="next"
32
+ :page="currentPage + 1"
33
+ :disabled="disabled || currentPage === total"
34
+ @click="goToPage"
35
+ />
36
+
37
+ <SkPaginationItem
38
+ v-if="showFirstLast"
39
+ type="last"
40
+ :page="total"
41
+ :disabled="disabled || currentPage === total"
42
+ @click="goToPage"
43
+ />
44
+ </nav>
45
+ </template>
46
+
47
+ <!--------------------------------------------------------------------------------------------------------------------->
48
+
49
+ <style lang="scss" scoped>
50
+ // Styles implemented in /src/styles/components/_pagination.scss
51
+ </style>
52
+
53
+ <!--------------------------------------------------------------------------------------------------------------------->
54
+
55
+ <script setup lang="ts">
56
+ import { computed, provide, toRef } from 'vue';
57
+
58
+ // Types
59
+ import type { ComponentCustomColors } from '@/types';
60
+ import type { SkPaginationProps } from './types';
61
+
62
+ //------------------------------------------------------------------------------------------------------------------
63
+
64
+ export interface SkPaginationComponentProps extends SkPaginationProps, ComponentCustomColors
65
+ {
66
+ }
67
+
68
+ //------------------------------------------------------------------------------------------------------------------
69
+
70
+ // Components
71
+ import SkPaginationItem from './SkPaginationItem.vue';
72
+
73
+ // Composables
74
+ import { useCustomColors } from '@/composables/useCustomColors';
75
+
76
+ //------------------------------------------------------------------------------------------------------------------
77
+
78
+ const props = withDefaults(defineProps<SkPaginationComponentProps>(), {
79
+ modelValue: 1,
80
+ siblingCount: 1,
81
+ showFirstLast: true,
82
+ showPrevNext: true,
83
+ kind: 'neutral',
84
+ size: 'md',
85
+ variant: 'solid',
86
+ disabled: false,
87
+ baseColor: undefined,
88
+ textColor: undefined,
89
+ });
90
+
91
+ const emit = defineEmits<{
92
+ 'update:modelValue' : [ page : number ];
93
+ }>();
94
+
95
+ //------------------------------------------------------------------------------------------------------------------
96
+
97
+ const currentPage = computed<number>({
98
+ get: () => props.modelValue,
99
+ set: (value) => emit('update:modelValue', value),
100
+ });
101
+
102
+ //------------------------------------------------------------------------------------------------------------------
103
+
104
+ provide('pagination-kind', toRef(() => props.kind));
105
+ provide('pagination-size', toRef(() => props.size));
106
+ provide('pagination-variant', toRef(() => props.variant));
107
+
108
+ //------------------------------------------------------------------------------------------------------------------
109
+
110
+ const customColorStyles = useCustomColors(
111
+ 'pagination',
112
+ toRef(() => props.baseColor),
113
+ toRef(() => props.textColor)
114
+ );
115
+
116
+ //------------------------------------------------------------------------------------------------------------------
117
+
118
+ const classes = computed(() => ({
119
+ 'sk-pagination': true,
120
+ [`sk-${ props.kind }`]: true,
121
+ [`sk-${ props.size }`]: true,
122
+ [`sk-${ props.variant }`]: true,
123
+ }));
124
+
125
+ const paginationRange = computed<(number | string)[]>(() =>
126
+ {
127
+ const range : (number | string)[] = [];
128
+
129
+ // If total pages fit in display, show all
130
+ const maxDisplay = 5 + (props.siblingCount * 2);
131
+ if(props.total <= maxDisplay)
132
+ {
133
+ return Array.from({ length: props.total }, (_, i) => i + 1);
134
+ }
135
+
136
+ // Always show first page
137
+ range.push(1);
138
+
139
+ // Calculate left and right boundaries
140
+ const leftSibling = Math.max(currentPage.value - props.siblingCount, 2);
141
+ const rightSibling = Math.min(currentPage.value + props.siblingCount, props.total - 1);
142
+
143
+ // Add left ellipsis if needed
144
+ if(leftSibling > 2)
145
+ {
146
+ range.push('...');
147
+ }
148
+
149
+ // Add sibling pages
150
+ for(let i = leftSibling; i <= rightSibling; i++)
151
+ {
152
+ range.push(i);
153
+ }
154
+
155
+ // Add right ellipsis if needed
156
+ if(rightSibling < props.total - 1)
157
+ {
158
+ range.push('...');
159
+ }
160
+
161
+ // Always show last page
162
+ if(props.total > 1)
163
+ {
164
+ range.push(props.total);
165
+ }
166
+
167
+ return range;
168
+ });
169
+
170
+ //------------------------------------------------------------------------------------------------------------------
171
+
172
+ function goToPage(page : number) : void
173
+ {
174
+ if(page < 1 || page > props.total || page === currentPage.value || props.disabled)
175
+ {
176
+ return;
177
+ }
178
+
179
+ currentPage.value = page;
180
+ }
181
+
182
+ //------------------------------------------------------------------------------------------------------------------
183
+ </script>
184
+
185
+ <!--------------------------------------------------------------------------------------------------------------------->