@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,88 @@
1
+ <!----------------------------------------------------------------------------------------------------------------------
2
+ - Sidebar Component
3
+ --------------------------------------------------------------------------------------------------------------------->
4
+
5
+ <template>
6
+ <aside :class="classes">
7
+ <SkPanel
8
+ :kind="kind"
9
+ :base-color="baseColor"
10
+ :text-color="textColor"
11
+ class="sk-sidebar-panel"
12
+ >
13
+ <div class="sk-panel-scroll-content">
14
+ <nav class="sk-sidebar-nav">
15
+ <slot />
16
+ </nav>
17
+ </div>
18
+ </SkPanel>
19
+ </aside>
20
+ </template>
21
+
22
+ <!--------------------------------------------------------------------------------------------------------------------->
23
+
24
+ <script setup lang="ts">
25
+ /**
26
+ * @component
27
+ * A sticky navigation sidebar container with semantic color theming.
28
+ * Wrap SkSidebarSection and SkSidebarItem components inside.
29
+ */
30
+
31
+ import { computed } from 'vue';
32
+ import type { SkSidebarKind } from './types';
33
+ import type { ComponentCustomColors } from '@/types';
34
+ import SkPanel from '../Panel/SkPanel.vue';
35
+
36
+ //------------------------------------------------------------------------------------------------------------------
37
+
38
+ /**
39
+ * A sticky navigation sidebar container with semantic color theming.
40
+ * Wrap SkSidebarSection and SkSidebarItem components inside.
41
+ *
42
+ * @example Basic sidebar
43
+ * ```vue
44
+ * <SkSidebar>
45
+ * <SkSidebarSection title="Navigation">
46
+ * <SkSidebarItem to="/home">Home</SkSidebarItem>
47
+ * <SkSidebarItem to="/about">About</SkSidebarItem>
48
+ * </SkSidebarSection>
49
+ * </SkSidebar>
50
+ * ```
51
+ *
52
+ * @example Custom colors
53
+ * ```vue
54
+ * <SkSidebar
55
+ * base-color="oklch(0.3 0.15 260)"
56
+ * text-color="oklch(0.85 0.05 260)"
57
+ * >
58
+ * <!-- Sidebar content -->
59
+ * </SkSidebar>
60
+ * ```
61
+ */
62
+ export interface SkSidebarComponentProps extends ComponentCustomColors
63
+ {
64
+ /** Semantic color kind for the sidebar */
65
+ kind ?: SkSidebarKind;
66
+ /** CSS width value for the sidebar */
67
+ width ?: string;
68
+ }
69
+
70
+ //------------------------------------------------------------------------------------------------------------------
71
+
72
+ const props = withDefaults(defineProps<SkSidebarComponentProps>(), {
73
+ kind: 'neutral',
74
+ width: '180px',
75
+ });
76
+
77
+ //------------------------------------------------------------------------------------------------------------------
78
+
79
+ const classes = computed(() =>
80
+ {
81
+ return {
82
+ 'sk-sidebar': true,
83
+ [`sk-${ props.kind }`]: true,
84
+ };
85
+ });
86
+ </script>
87
+
88
+ <!--------------------------------------------------------------------------------------------------------------------->
@@ -0,0 +1,58 @@
1
+ <!----------------------------------------------------------------------------------------------------------------------
2
+ - Sidebar Item Component
3
+ --------------------------------------------------------------------------------------------------------------------->
4
+
5
+ <template>
6
+ <component
7
+ :is="as"
8
+ :class="classes"
9
+ v-bind="$attrs"
10
+ >
11
+ <slot />
12
+ </component>
13
+ </template>
14
+
15
+ <!--------------------------------------------------------------------------------------------------------------------->
16
+
17
+ <script setup lang="ts">
18
+ /**
19
+ * @component
20
+ * An individual navigation item in the sidebar.
21
+ * Can render as any element (a, RouterLink, button, etc).
22
+ */
23
+
24
+ import { computed } from 'vue';
25
+
26
+ //------------------------------------------------------------------------------------------------------------------
27
+
28
+ /**
29
+ * An individual navigation item in the sidebar.
30
+ * Can render as any element (a, RouterLink, button, etc).
31
+ */
32
+ export interface SkSidebarItemComponentProps
33
+ {
34
+ /** HTML tag or component name to render as */
35
+ as ?: string;
36
+ /** Whether this item is currently active */
37
+ active ?: boolean;
38
+ }
39
+
40
+ //------------------------------------------------------------------------------------------------------------------
41
+
42
+ const props = withDefaults(defineProps<SkSidebarItemComponentProps>(), {
43
+ as: 'a',
44
+ active: false,
45
+ });
46
+
47
+ //------------------------------------------------------------------------------------------------------------------
48
+
49
+ const classes = computed(() =>
50
+ {
51
+ return {
52
+ 'sk-sidebar-item': true,
53
+ 'sk-active': props.active,
54
+ };
55
+ });
56
+ </script>
57
+
58
+ <!--------------------------------------------------------------------------------------------------------------------->
@@ -0,0 +1,40 @@
1
+ <!----------------------------------------------------------------------------------------------------------------------
2
+ - Sidebar Section Component
3
+ --------------------------------------------------------------------------------------------------------------------->
4
+
5
+ <template>
6
+ <div class="sk-sidebar-section">
7
+ <h3 v-if="title" class="sk-sidebar-section-title">
8
+ {{ title }}
9
+ </h3>
10
+ <slot />
11
+ </div>
12
+ </template>
13
+
14
+ <!--------------------------------------------------------------------------------------------------------------------->
15
+
16
+ <script setup lang="ts">
17
+ /**
18
+ * @component
19
+ * Groups sidebar items under an optional heading.
20
+ * Use this to organize navigation into logical sections.
21
+ */
22
+
23
+ //------------------------------------------------------------------------------------------------------------------
24
+
25
+ /**
26
+ * Groups sidebar items under an optional heading.
27
+ * Use this to organize navigation into logical sections.
28
+ */
29
+ export interface SkSidebarSectionComponentProps
30
+ {
31
+ /** Optional section heading */
32
+ title ?: string;
33
+ }
34
+
35
+ //------------------------------------------------------------------------------------------------------------------
36
+
37
+ defineProps<SkSidebarSectionComponentProps>();
38
+ </script>
39
+
40
+ <!--------------------------------------------------------------------------------------------------------------------->
@@ -0,0 +1,3 @@
1
+ import type { ComponentKind } from '@/types';
2
+
3
+ export type SkSidebarKind = ComponentKind;
@@ -0,0 +1,171 @@
1
+ <template>
2
+ <div
3
+ :class="classes"
4
+ :style="styles"
5
+ />
6
+ </template>
7
+
8
+ <!--------------------------------------------------------------------------------------------------------------------->
9
+
10
+ <style lang="scss" scoped>
11
+ // Component styles are implemented in /src/styles/components/_skeleton.scss
12
+ </style>
13
+
14
+ <!--------------------------------------------------------------------------------------------------------------------->
15
+
16
+ <script setup lang="ts">
17
+ /**
18
+ * @component SkSkeleton
19
+ * A loading placeholder component with shimmer or pulse animation.
20
+ * Use to indicate loading state while content is being fetched.
21
+ */
22
+
23
+ import { computed } from 'vue';
24
+
25
+ // Types
26
+ import type { SkSkeletonAnimation, SkSkeletonCorner, SkSkeletonVariant } from './types';
27
+
28
+ //------------------------------------------------------------------------------------------------------------------
29
+
30
+ export interface SkSkeletonComponentProps
31
+ {
32
+ /** Shape variant */
33
+ variant ?: SkSkeletonVariant;
34
+ /** Width (CSS value) */
35
+ width ?: string;
36
+ /** Height (CSS value) */
37
+ height ?: string;
38
+ /** Animation style */
39
+ animation ?: SkSkeletonAnimation;
40
+ /** Custom corners to bevel (overrides variant default) */
41
+ corners ?: SkSkeletonCorner[];
42
+ /** Custom bevel size (CSS value, e.g. '0.5rem', '8px') */
43
+ bevel ?: string;
44
+ }
45
+
46
+ //------------------------------------------------------------------------------------------------------------------
47
+
48
+ const props = withDefaults(defineProps<SkSkeletonComponentProps>(), {
49
+ variant: 'text',
50
+ width: '100%',
51
+ height: undefined,
52
+ animation: 'shimmer',
53
+ corners: undefined,
54
+ bevel: undefined,
55
+ });
56
+
57
+ //------------------------------------------------------------------------------------------------------------------
58
+ // Clip Path Generation
59
+ //------------------------------------------------------------------------------------------------------------------
60
+
61
+ /**
62
+ * Generates a clip-path polygon for beveled corners.
63
+ * @param corners - Array of corners to bevel
64
+ * @param bevel - CSS value for bevel size
65
+ */
66
+ function generateClipPath(corners : SkSkeletonCorner[], bevel : string) : string
67
+ {
68
+ const hasCorner = (corner : SkSkeletonCorner) : boolean => corners.includes(corner);
69
+
70
+ // Build polygon points clockwise from top-left
71
+ const points : string[] = [];
72
+
73
+ // Top-left corner
74
+ if(hasCorner('top-left'))
75
+ {
76
+ points.push(`${ bevel } 0`);
77
+ }
78
+ else
79
+ {
80
+ points.push('0 0');
81
+ }
82
+
83
+ // Top-right corner
84
+ if(hasCorner('top-right'))
85
+ {
86
+ points.push(`calc(100% - ${ bevel }) 0`);
87
+ points.push(`100% ${ bevel }`);
88
+ }
89
+ else
90
+ {
91
+ points.push('100% 0');
92
+ }
93
+
94
+ // Bottom-right corner
95
+ if(hasCorner('bottom-right'))
96
+ {
97
+ points.push(`100% calc(100% - ${ bevel })`);
98
+ points.push(`calc(100% - ${ bevel }) 100%`);
99
+ }
100
+ else
101
+ {
102
+ points.push('100% 100%');
103
+ }
104
+
105
+ // Bottom-left corner
106
+ if(hasCorner('bottom-left'))
107
+ {
108
+ points.push(`${ bevel } 100%`);
109
+ points.push(`0 calc(100% - ${ bevel })`);
110
+ }
111
+ else
112
+ {
113
+ points.push('0 100%');
114
+ }
115
+
116
+ // Close top-left if beveled
117
+ if(hasCorner('top-left'))
118
+ {
119
+ points.push(`0 ${ bevel }`);
120
+ }
121
+
122
+ return `polygon(${ points.join(', ') })`;
123
+ }
124
+
125
+ //------------------------------------------------------------------------------------------------------------------
126
+ // Classes
127
+ //------------------------------------------------------------------------------------------------------------------
128
+
129
+ const classes = computed(() => ({
130
+ 'sk-skeleton': true,
131
+ [`sk-${ props.variant }`]: true,
132
+ [`sk-${ props.animation }`]: props.animation !== 'none',
133
+ 'sk-custom-corners': !!props.corners,
134
+ }));
135
+
136
+ //------------------------------------------------------------------------------------------------------------------
137
+ // Styles
138
+ //------------------------------------------------------------------------------------------------------------------
139
+
140
+ const styles = computed(() =>
141
+ {
142
+ const result : Record<string, string> = {};
143
+
144
+ if(props.width)
145
+ {
146
+ result.width = props.width;
147
+ }
148
+
149
+ if(props.height)
150
+ {
151
+ result.height = props.height;
152
+ }
153
+
154
+ // For circular or square variant, if only width is set, make it square
155
+ if((props.variant === 'circular' || props.variant === 'square') && props.width && !props.height)
156
+ {
157
+ result.height = props.width;
158
+ }
159
+
160
+ // Generate custom clip-path if corners are specified
161
+ if(props.corners && props.corners.length > 0)
162
+ {
163
+ const bevelSize = props.bevel ?? '0.5rem';
164
+ result.clipPath = generateClipPath(props.corners, bevelSize);
165
+ }
166
+
167
+ return result;
168
+ });
169
+ </script>
170
+
171
+ <!--------------------------------------------------------------------------------------------------------------------->
@@ -0,0 +1,8 @@
1
+ //----------------------------------------------------------------------------------------------------------------------
2
+ // Skeleton Component Exports
3
+ //----------------------------------------------------------------------------------------------------------------------
4
+
5
+ export { default as SkSkeleton } from './SkSkeleton.vue';
6
+ export * from './types';
7
+
8
+ //----------------------------------------------------------------------------------------------------------------------
@@ -0,0 +1,31 @@
1
+ //----------------------------------------------------------------------------------------------------------------------
2
+ // Skeleton Types
3
+ //----------------------------------------------------------------------------------------------------------------------
4
+
5
+ /** Skeleton shape variant */
6
+ export type SkSkeletonVariant = 'text' | 'circular' | 'rectangular' | 'square';
7
+
8
+ /** Skeleton animation style */
9
+ export type SkSkeletonAnimation = 'shimmer' | 'pulse' | 'none';
10
+
11
+ /** Corner positions for beveling */
12
+ export type SkSkeletonCorner = 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';
13
+
14
+ /** Skeleton props interface */
15
+ export interface SkSkeletonProps
16
+ {
17
+ /** Shape variant */
18
+ variant ?: SkSkeletonVariant;
19
+ /** Width (CSS value) */
20
+ width ?: string;
21
+ /** Height (CSS value) */
22
+ height ?: string;
23
+ /** Animation style */
24
+ animation ?: SkSkeletonAnimation;
25
+ /** Custom corners to bevel (overrides variant default) */
26
+ corners ?: SkSkeletonCorner[];
27
+ /** Custom bevel size (CSS value, e.g. '0.5rem', '8px') */
28
+ bevel ?: string;
29
+ }
30
+
31
+ //----------------------------------------------------------------------------------------------------------------------
@@ -0,0 +1,165 @@
1
+ <template>
2
+ <SliderRoot
3
+ :model-value="normalizedValue"
4
+ :min="min"
5
+ :max="max"
6
+ :step="step"
7
+ :orientation="orientation"
8
+ :disabled="disabled"
9
+ :name="name"
10
+ :min-steps-between-thumbs="minStepsBetweenThumbs"
11
+ :class="classes"
12
+ :style="customStyles"
13
+ @update:model-value="handleUpdate"
14
+ >
15
+ <SliderTrack class="sk-slider-track">
16
+ <SliderRange class="sk-slider-range" />
17
+ </SliderTrack>
18
+ <SliderThumb
19
+ v-for="(_, index) in thumbCount"
20
+ :key="index"
21
+ class="sk-slider-thumb"
22
+ />
23
+ </SliderRoot>
24
+ </template>
25
+
26
+ <!--------------------------------------------------------------------------------------------------------------------->
27
+
28
+ <style lang="scss" scoped>
29
+ // Component styles are implemented in /src/styles/components/_slider.scss
30
+ </style>
31
+
32
+ <!--------------------------------------------------------------------------------------------------------------------->
33
+
34
+ <script setup lang="ts">
35
+ /**
36
+ * @component SkSlider
37
+ * A range slider component for selecting numeric values.
38
+ * Supports single and multi-thumb (range) modes.
39
+ * Powered by RekaUI with all 7 semantic kinds and custom colors.
40
+ */
41
+
42
+ import { computed } from 'vue';
43
+ import { SliderRange, SliderRoot, SliderThumb, SliderTrack } from 'reka-ui';
44
+
45
+ // Types
46
+ import type { ComponentKind } from '@/types';
47
+ import type { SkSliderOrientation, SkSliderSize } from './types';
48
+
49
+ //------------------------------------------------------------------------------------------------------------------
50
+
51
+ export interface SkSliderComponentProps
52
+ {
53
+ /** Current value(s) of the slider */
54
+ modelValue : number | number[];
55
+ /** Minimum value */
56
+ min ?: number;
57
+ /** Maximum value */
58
+ max ?: number;
59
+ /** Step increment */
60
+ step ?: number;
61
+ /** Semantic color kind */
62
+ kind ?: ComponentKind;
63
+ /** Slider size */
64
+ size ?: SkSliderSize;
65
+ /** Slider orientation */
66
+ orientation ?: SkSliderOrientation;
67
+ /** Whether the slider is disabled */
68
+ disabled ?: boolean;
69
+ /** Name attribute for form submission */
70
+ name ?: string;
71
+ /** Minimum steps between thumbs for range slider */
72
+ minStepsBetweenThumbs ?: number;
73
+ /** Custom track color (overrides kind) */
74
+ baseColor ?: string;
75
+ /** Custom thumb color */
76
+ thumbColor ?: string;
77
+ }
78
+
79
+ //------------------------------------------------------------------------------------------------------------------
80
+
81
+ const props = withDefaults(defineProps<SkSliderComponentProps>(), {
82
+ min: 0,
83
+ max: 100,
84
+ step: 1,
85
+ kind: 'primary',
86
+ size: 'md',
87
+ orientation: 'horizontal',
88
+ disabled: false,
89
+ name: undefined,
90
+ minStepsBetweenThumbs: 0,
91
+ baseColor: undefined,
92
+ thumbColor: undefined,
93
+ });
94
+
95
+ const emit = defineEmits<{
96
+ 'update:modelValue' : [value : number | number[]];
97
+ }>();
98
+
99
+ //------------------------------------------------------------------------------------------------------------------
100
+ // Computed
101
+ //------------------------------------------------------------------------------------------------------------------
102
+
103
+ // Normalize single value to array for RekaUI
104
+ const normalizedValue = computed(() =>
105
+ {
106
+ return Array.isArray(props.modelValue) ? props.modelValue : [ props.modelValue ];
107
+ });
108
+
109
+ const thumbCount = computed(() =>
110
+ {
111
+ return normalizedValue.value.length;
112
+ });
113
+
114
+ const classes = computed(() => ({
115
+ 'sk-slider': true,
116
+ [`sk-${ props.kind }`]: true,
117
+ [`sk-${ props.size }`]: true,
118
+ [`sk-${ props.orientation }`]: true,
119
+ }));
120
+
121
+ //------------------------------------------------------------------------------------------------------------------
122
+ // Custom Colors
123
+ //------------------------------------------------------------------------------------------------------------------
124
+
125
+ const customStyles = computed(() =>
126
+ {
127
+ const styles : Record<string, string> = {};
128
+
129
+ if(props.baseColor)
130
+ {
131
+ styles['--sk-slider-color-base'] = props.baseColor;
132
+ }
133
+
134
+ if(props.thumbColor)
135
+ {
136
+ styles['--sk-slider-thumb-color'] = props.thumbColor;
137
+ }
138
+
139
+ return styles;
140
+ });
141
+
142
+ //------------------------------------------------------------------------------------------------------------------
143
+ // Methods
144
+ //------------------------------------------------------------------------------------------------------------------
145
+
146
+ function handleUpdate(value : number[] | undefined) : void
147
+ {
148
+ if(!value)
149
+ {
150
+ return;
151
+ }
152
+
153
+ // If original modelValue was a single number, emit single number
154
+ if(!Array.isArray(props.modelValue))
155
+ {
156
+ emit('update:modelValue', value[0]);
157
+ }
158
+ else
159
+ {
160
+ emit('update:modelValue', value);
161
+ }
162
+ }
163
+ </script>
164
+
165
+ <!--------------------------------------------------------------------------------------------------------------------->
@@ -0,0 +1,8 @@
1
+ //----------------------------------------------------------------------------------------------------------------------
2
+ // Slider Component
3
+ //----------------------------------------------------------------------------------------------------------------------
4
+
5
+ export { default } from './SkSlider.vue';
6
+ export * from './types';
7
+
8
+ //----------------------------------------------------------------------------------------------------------------------
@@ -0,0 +1,44 @@
1
+ //----------------------------------------------------------------------------------------------------------------------
2
+ // Slider Types
3
+ //----------------------------------------------------------------------------------------------------------------------
4
+
5
+ import type { ComponentKind, ComponentSize } from '@/types';
6
+
7
+ //----------------------------------------------------------------------------------------------------------------------
8
+
9
+ /** Slider size */
10
+ export type SkSliderSize = ComponentSize;
11
+
12
+ /** Slider orientation */
13
+ export type SkSliderOrientation = 'horizontal' | 'vertical';
14
+
15
+ /** Slider props interface */
16
+ export interface SkSliderProps
17
+ {
18
+ /** Current value(s) of the slider */
19
+ modelValue : number | number[];
20
+ /** Minimum value */
21
+ min ?: number;
22
+ /** Maximum value */
23
+ max ?: number;
24
+ /** Step increment */
25
+ step ?: number;
26
+ /** Semantic color kind */
27
+ kind ?: ComponentKind;
28
+ /** Slider size */
29
+ size ?: SkSliderSize;
30
+ /** Slider orientation */
31
+ orientation ?: SkSliderOrientation;
32
+ /** Whether the slider is disabled */
33
+ disabled ?: boolean;
34
+ /** Name attribute for form submission */
35
+ name ?: string;
36
+ /** Whether multiple thumbs are allowed (range slider) */
37
+ minStepsBetweenThumbs ?: number;
38
+ /** Custom track color (overrides kind) */
39
+ baseColor ?: string;
40
+ /** Custom thumb color */
41
+ thumbColor ?: string;
42
+ }
43
+
44
+ //----------------------------------------------------------------------------------------------------------------------