@skewedaspect/sleekspace-ui 0.8.1 → 0.9.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 (191) hide show
  1. package/dist/components/Dropdown/SkDropdown.vue.d.ts +9 -1
  2. package/dist/components/Dropdown/types.d.ts +2 -1
  3. package/dist/components/NavBar/SkNavBar.vue.d.ts +9 -1
  4. package/dist/components/NavBar/context.d.ts +2 -0
  5. package/dist/components/NavBar/types.d.ts +5 -1
  6. package/dist/components/NumberInput/SkNumberInput.vue.d.ts +8 -0
  7. package/dist/components/Page/SkPage.vue.d.ts +9 -0
  8. package/dist/components/ScrollArea/SkScrollArea.vue.d.ts +105 -4
  9. package/dist/composables/useCustomColors.d.ts +18 -56
  10. package/{src → dist}/global.d.ts +6 -2
  11. package/dist/sleekspace-ui.css +4257 -1253
  12. package/dist/sleekspace-ui.es.js +300 -170
  13. package/dist/sleekspace-ui.umd.js +299 -169
  14. package/dist/static/classes.d.ts +18 -0
  15. package/dist/static/components/alert.d.ts +12 -0
  16. package/dist/static/components/avatar.d.ts +9 -0
  17. package/dist/static/components/breadcrumbs.d.ts +6 -0
  18. package/dist/static/components/button.d.ts +13 -0
  19. package/dist/static/components/card.d.ts +5 -0
  20. package/dist/static/components/checkbox.d.ts +10 -0
  21. package/dist/static/components/colorPicker.d.ts +8 -0
  22. package/dist/static/components/divider.d.ts +8 -0
  23. package/dist/static/components/dropdown.d.ts +8 -0
  24. package/dist/static/components/field.d.ts +15 -0
  25. package/dist/static/components/group.d.ts +5 -0
  26. package/dist/static/components/input.d.ts +14 -0
  27. package/dist/static/components/navBar.d.ts +16 -0
  28. package/dist/static/components/numberInput.d.ts +15 -0
  29. package/dist/static/components/page.d.ts +9 -0
  30. package/dist/static/components/pagination.d.ts +5 -0
  31. package/dist/static/components/panel.d.ts +11 -0
  32. package/dist/static/components/progress.d.ts +9 -0
  33. package/dist/static/components/radio.d.ts +11 -0
  34. package/dist/static/components/select.d.ts +10 -0
  35. package/dist/static/components/sidebar.d.ts +9 -0
  36. package/dist/static/components/skeleton.d.ts +11 -0
  37. package/dist/static/components/slider.d.ts +12 -0
  38. package/dist/static/components/spinner.d.ts +12 -0
  39. package/dist/static/components/switchInput.d.ts +10 -0
  40. package/dist/static/components/table.d.ts +12 -0
  41. package/dist/static/components/tag.d.ts +8 -0
  42. package/dist/static/components/tagsInput.d.ts +7 -0
  43. package/dist/static/components/textarea.d.ts +12 -0
  44. package/dist/static/components/toolbar.d.ts +12 -0
  45. package/dist/static/components/tooltip.d.ts +7 -0
  46. package/dist/static/escape.d.ts +2 -0
  47. package/dist/static/index.cjs.js +1 -0
  48. package/dist/static/index.d.ts +68 -0
  49. package/dist/static/index.es.js +732 -0
  50. package/dist/static/render.d.ts +12 -0
  51. package/dist/static/specs.d.ts +2 -0
  52. package/dist/static/types.d.ts +43 -0
  53. package/dist/tokens.css +322 -0
  54. package/dist/types/index.d.ts +36 -0
  55. package/dist/utils/slots.d.ts +6 -0
  56. package/docs/guides/installation.md +8 -2
  57. package/docs/guides/pure-css/_meta.yaml +8 -0
  58. package/docs/guides/pure-css/class-api.md +1070 -0
  59. package/docs/guides/pure-css/custom-elements.md +574 -0
  60. package/docs/guides/pure-css/index.md +86 -0
  61. package/docs/guides/pure-css/limitations.md +152 -0
  62. package/docs/guides/pure-css/static-helpers.md +1203 -0
  63. package/llms-full.txt +3739 -261
  64. package/package.json +19 -5
  65. package/src/components/Alert/SkAlert.vue +4 -2
  66. package/src/components/Breadcrumbs/SkBreadcrumbs.vue +6 -12
  67. package/src/components/Button/SkButton.vue +8 -5
  68. package/src/components/Card/SkCard.vue +13 -5
  69. package/src/components/Checkbox/SkCheckbox.vue +9 -2
  70. package/src/components/ContextMenu/SkContextMenuRadioGroup.vue +4 -1
  71. package/src/components/Dropdown/SkDropdown.vue +20 -3
  72. package/src/components/Dropdown/SkDropdownRadioGroup.vue +4 -1
  73. package/src/components/Dropdown/types.ts +2 -1
  74. package/src/components/Modal/SkModal.vue +11 -4
  75. package/src/components/NavBar/SkNavBar.vue +19 -8
  76. package/src/components/NavBar/context.ts +4 -2
  77. package/src/components/NavBar/types.ts +6 -1
  78. package/src/components/NumberInput/SkNumberInput.vue +10 -1
  79. package/src/components/Page/SkPage.vue +29 -15
  80. package/src/components/Panel/SkPanel.vue +2 -1
  81. package/src/components/Popover/SkPopover.vue +11 -4
  82. package/src/components/Radio/SkRadio.vue +9 -2
  83. package/src/components/ScrollArea/SkScrollArea.vue +78 -5
  84. package/src/components/Switch/SkSwitch.vue +14 -13
  85. package/src/components/Tabs/SkTab.vue +7 -2
  86. package/src/components/TreeView/SkTreeItem.vue +10 -2
  87. package/src/components/TreeView/SkTreeView.vue +7 -2
  88. package/src/composables/useCustomColors.ts +86 -77
  89. package/src/composables/usePortalContext.test.ts +0 -2
  90. package/src/shims.d.ts +10 -0
  91. package/src/static/__tests__/parity.test.ts +717 -0
  92. package/src/static/__tests__/parityHarness.test.ts +98 -0
  93. package/src/static/__tests__/parityHarness.ts +260 -0
  94. package/src/static/classes.test.ts +82 -0
  95. package/src/static/classes.ts +111 -0
  96. package/src/static/components/__tests__/helpers.test.ts +837 -0
  97. package/src/static/components/alert.ts +117 -0
  98. package/src/static/components/avatar.ts +86 -0
  99. package/src/static/components/breadcrumbs.ts +28 -0
  100. package/src/static/components/button.ts +75 -0
  101. package/src/static/components/card.ts +27 -0
  102. package/src/static/components/checkbox.ts +48 -0
  103. package/src/static/components/colorPicker.ts +45 -0
  104. package/src/static/components/divider.ts +39 -0
  105. package/src/static/components/dropdown.ts +36 -0
  106. package/src/static/components/field.ts +86 -0
  107. package/src/static/components/group.ts +27 -0
  108. package/src/static/components/input.ts +55 -0
  109. package/src/static/components/navBar.ts +94 -0
  110. package/src/static/components/numberInput.ts +64 -0
  111. package/src/static/components/page.ts +31 -0
  112. package/src/static/components/pagination.ts +27 -0
  113. package/src/static/components/panel.ts +33 -0
  114. package/src/static/components/progress.ts +31 -0
  115. package/src/static/components/radio.ts +53 -0
  116. package/src/static/components/select.ts +51 -0
  117. package/src/static/components/sidebar.ts +85 -0
  118. package/src/static/components/skeleton.ts +66 -0
  119. package/src/static/components/slider.ts +50 -0
  120. package/src/static/components/spinner.ts +94 -0
  121. package/src/static/components/switchInput.ts +49 -0
  122. package/src/static/components/table.ts +88 -0
  123. package/src/static/components/tag.ts +76 -0
  124. package/src/static/components/tagsInput.ts +35 -0
  125. package/src/static/components/textarea.ts +53 -0
  126. package/src/static/components/toolbar.ts +74 -0
  127. package/src/static/components/tooltip.ts +29 -0
  128. package/src/static/escape.test.ts +53 -0
  129. package/src/static/escape.ts +28 -0
  130. package/src/static/generated/defaults.ts +379 -0
  131. package/src/static/generated/propTypes.ts +426 -0
  132. package/src/static/index.ts +116 -0
  133. package/src/static/render.test.ts +83 -0
  134. package/src/static/render.ts +76 -0
  135. package/src/static/specs.test.ts +58 -0
  136. package/src/static/specs.ts +230 -0
  137. package/src/static/types.ts +176 -0
  138. package/src/styles/__tests__/testHelpers.ts +97 -0
  139. package/src/styles/base/_custom-elements.scss +51 -0
  140. package/src/styles/base/_index.scss +4 -0
  141. package/src/styles/components/__tests__/componentSelectors.test.ts +2575 -0
  142. package/src/styles/components/_alert.scss +82 -39
  143. package/src/styles/components/_avatar.scss +102 -47
  144. package/src/styles/components/_breadcrumbs.scss +39 -37
  145. package/src/styles/components/_button.scss +58 -5
  146. package/src/styles/components/_card.scss +64 -2
  147. package/src/styles/components/_checkbox.scss +35 -5
  148. package/src/styles/components/_color-picker.scss +48 -13
  149. package/src/styles/components/_divider.scss +86 -52
  150. package/src/styles/components/_dropdown.scss +214 -0
  151. package/src/styles/components/_field.scss +76 -23
  152. package/src/styles/components/_group.scss +190 -79
  153. package/src/styles/components/_index.scss +1 -0
  154. package/src/styles/components/_input.scss +81 -5
  155. package/src/styles/components/_menu.scss +1 -1
  156. package/src/styles/components/_navbar.scss +76 -45
  157. package/src/styles/components/_number-input.scss +98 -85
  158. package/src/styles/components/_page.scss +82 -23
  159. package/src/styles/components/_pagination.scss +240 -212
  160. package/src/styles/components/_panel.scss +268 -122
  161. package/src/styles/components/_progress.scss +120 -70
  162. package/src/styles/components/_radio.scss +35 -5
  163. package/src/styles/components/_scroll-area.scss +50 -22
  164. package/src/styles/components/_select.scss +40 -9
  165. package/src/styles/components/_sidebar.scss +59 -34
  166. package/src/styles/components/_skeleton.scss +111 -65
  167. package/src/styles/components/_slider.scss +34 -10
  168. package/src/styles/components/_spinner.scss +107 -56
  169. package/src/styles/components/_switch.scss +36 -5
  170. package/src/styles/components/_table.scss +150 -166
  171. package/src/styles/components/_tag.scss +244 -154
  172. package/src/styles/components/_tags-input.scss +46 -12
  173. package/src/styles/components/_textarea.scss +36 -5
  174. package/src/styles/components/_toolbar.scss +85 -31
  175. package/src/styles/components/_tooltip.scss +172 -3
  176. package/src/styles/mixins/_cut-border.scss +18 -4
  177. package/src/styles/mixins/_dual-selector.scss +192 -0
  178. package/src/styles/mixins/_index.scss +1 -0
  179. package/src/styles/mixins/dualSelector.test.ts +151 -0
  180. package/src/styles/themes/_colorful.scss +25 -0
  181. package/src/styles/themes/_greyscale.scss +25 -0
  182. package/src/styles/themes/_shade-scale.scss +39 -0
  183. package/src/styles/tokens/_semantic-color-kinds.scss +66 -0
  184. package/src/{types.ts → types/index.ts} +19 -11
  185. package/src/utils/slots.ts +75 -0
  186. package/web-types.json +980 -137
  187. package/dist/composables/useCustomColors.test.d.ts +0 -1
  188. package/dist/composables/useFocusTrap.test.d.ts +0 -1
  189. package/dist/composables/usePortalContext.test.d.ts +0 -1
  190. package/dist/styles/mixins/fluidSize.test.d.ts +0 -1
  191. package/dist/types.d.ts +0 -29
@@ -0,0 +1,55 @@
1
+ //----------------------------------------------------------------------------------------------------------------------
2
+ // Input Static Helper
3
+ //
4
+ // Emits a void <input class="sk-input" /> with passthrough attrs for type, value, placeholder,
5
+ // name, id, and boolean attrs (disabled, readonly, required).
6
+ //----------------------------------------------------------------------------------------------------------------------
7
+
8
+ import type { ComponentKind, ComponentSize } from '../types';
9
+
10
+ import { composeClasses } from '../classes';
11
+ import { escapeAttr } from '../escape';
12
+
13
+ //----------------------------------------------------------------------------------------------------------------------
14
+
15
+ export interface InputStaticProps
16
+ {
17
+ kind ?: ComponentKind;
18
+ size ?: ComponentSize;
19
+ type ?: string;
20
+ value ?: string;
21
+ placeholder ?: string;
22
+ name ?: string;
23
+ id ?: string;
24
+ disabled ?: boolean;
25
+ readonly ?: boolean;
26
+ required ?: boolean;
27
+ }
28
+
29
+ //----------------------------------------------------------------------------------------------------------------------
30
+
31
+ export function input(props : InputStaticProps = {}) : string
32
+ {
33
+ const classes = composeClasses({ base: 'sk-input', kind: true, size: true }, props as Record<string, unknown>);
34
+ const attrs : string[] = [ `class="${ escapeAttr(classes) }"` ];
35
+
36
+ const passthroughString = [ 'type', 'value', 'placeholder', 'name', 'id' ] as const;
37
+ for(const key of passthroughString)
38
+ {
39
+ const val = props[key];
40
+ if(typeof val === 'string')
41
+ {
42
+ attrs.push(`${ key }="${ escapeAttr(val) }"`);
43
+ }
44
+ }
45
+
46
+ const passthroughBool = [ 'disabled', 'readonly', 'required' ] as const;
47
+ for(const key of passthroughBool)
48
+ {
49
+ if(props[key] === true) { attrs.push(key); }
50
+ }
51
+
52
+ return `<input ${ attrs.join(' ') } />`;
53
+ }
54
+
55
+ //----------------------------------------------------------------------------------------------------------------------
@@ -0,0 +1,94 @@
1
+ //----------------------------------------------------------------------------------------------------------------------
2
+ // NavBar Static Helper
3
+ //
4
+ // Emits the full navbar DOM structure matching the Vue component's rendered output:
5
+ // <nav class="sk-navbar ...">
6
+ // <div class="sk-navbar-content">
7
+ // [<div class="sk-navbar-leading">...</div>] (only when leading prop provided)
8
+ // [<div class="sk-navbar-brand">...</div>] (only when brand prop provided)
9
+ // [<div class="sk-navbar-nav">...</div>] (only when children provided)
10
+ // [<div class="sk-navbar-actions">...</div>] (only when actions prop provided)
11
+ // </div>
12
+ // </nav>
13
+ //
14
+ // The `children` argument maps to the default (nav links) slot. Additional slot content is
15
+ // provided via the `leading`, `brand`, and `actions` props.
16
+ //----------------------------------------------------------------------------------------------------------------------
17
+
18
+ import type { NavBarKind, StaticCustomColors } from '../types';
19
+
20
+ import { composeClasses } from '../classes';
21
+ import { escapeAttr } from '../escape';
22
+
23
+ //----------------------------------------------------------------------------------------------------------------------
24
+
25
+ export interface NavBarStaticProps extends StaticCustomColors
26
+ {
27
+ kind ?: NavBarKind;
28
+
29
+ /**
30
+ * When true (default), applies `sk-sticky` class — matches Vue's `sticky: true` default.
31
+ * @default true
32
+ */
33
+ sticky ?: boolean;
34
+
35
+ /** HTML for the leading slot (far-left area, e.g. sidebar toggle). */
36
+ leading ?: string;
37
+
38
+ /** HTML for the brand slot (logo / site name). */
39
+ brand ?: string;
40
+
41
+ /** HTML for the actions slot (right-aligned CTAs / user menu). */
42
+ actions ?: string;
43
+ }
44
+
45
+ //----------------------------------------------------------------------------------------------------------------------
46
+
47
+ export function navBar(props : NavBarStaticProps = {}, children = '') : string
48
+ {
49
+ // Sticky defaults to true — matches Vue's withDefaults({ sticky: true })
50
+ const sticky = props.sticky !== false;
51
+
52
+ const classes = composeClasses(
53
+ {
54
+ base: 'sk-navbar',
55
+ kind: true,
56
+ // Handle sticky manually below (default-true boolean doesn't fit booleanFlags which
57
+ // only adds the class when prop === true; we need it when prop !== false)
58
+ },
59
+ props as Record<string, unknown>
60
+ );
61
+
62
+ // Append sk-sticky when sticky is enabled
63
+ const fullClasses = sticky ? `${ classes } sk-sticky` : classes;
64
+
65
+ const attrs : string[] = [ `class="${ escapeAttr(fullClasses) }"` ];
66
+
67
+ // Custom color vars
68
+ const styleParts : string[] = [];
69
+ if(typeof props.baseColor === 'string')
70
+ {
71
+ styleParts.push(`--sk-navbar-color-base: ${ escapeAttr(props.baseColor) };`);
72
+ }
73
+ if(typeof props.textColor === 'string')
74
+ {
75
+ styleParts.push(`--sk-navbar-fg: ${ escapeAttr(props.textColor) };`);
76
+ }
77
+ if(styleParts.length > 0)
78
+ {
79
+ attrs.push(`style="${ styleParts.join(' ') }"`);
80
+ }
81
+
82
+ // Build inner slot regions — each is only emitted when content is non-empty, matching Vue's v-if
83
+ let inner = '';
84
+ if(props.leading) { inner += `<div class="sk-navbar-leading">${ props.leading }</div>`; }
85
+ if(props.brand) { inner += `<div class="sk-navbar-brand">${ props.brand }</div>`; }
86
+ if(children) { inner += `<div class="sk-navbar-nav">${ children }</div>`; }
87
+ if(props.actions) { inner += `<div class="sk-navbar-actions">${ props.actions }</div>`; }
88
+
89
+ const content = `<div class="sk-navbar-content">${ inner }</div>`;
90
+
91
+ return `<nav ${ attrs.join(' ') }>${ content }</nav>`;
92
+ }
93
+
94
+ //----------------------------------------------------------------------------------------------------------------------
@@ -0,0 +1,64 @@
1
+ //----------------------------------------------------------------------------------------------------------------------
2
+ // NumberInput Static Helper
3
+ //
4
+ // Emits a compound <div class="sk-number-input-wrapper">
5
+ // <input class="sk-number-input-field" type="number" ... /></div> structure.
6
+ // Stepper buttons are intentionally omitted — they require JS to function and aren't
7
+ // meaningful in a static/SSG context.
8
+ //----------------------------------------------------------------------------------------------------------------------
9
+
10
+ import type { ComponentKind, ComponentSize } from '../types';
11
+
12
+ import { composeClasses } from '../classes';
13
+ import { escapeAttr } from '../escape';
14
+
15
+ //----------------------------------------------------------------------------------------------------------------------
16
+
17
+ export interface NumberInputStaticProps
18
+ {
19
+ kind ?: ComponentKind;
20
+ size ?: ComponentSize;
21
+ value ?: string;
22
+ min ?: string;
23
+ max ?: string;
24
+ step ?: string;
25
+ name ?: string;
26
+ placeholder ?: string;
27
+ disabled ?: boolean;
28
+ readonly ?: boolean;
29
+ required ?: boolean;
30
+ }
31
+
32
+ //----------------------------------------------------------------------------------------------------------------------
33
+
34
+ export function numberInput(props : NumberInputStaticProps = {}) : string
35
+ {
36
+ const wrapperClasses = composeClasses(
37
+ { base: 'sk-number-input-wrapper', kind: true, size: true },
38
+ props as Record<string, unknown>
39
+ );
40
+
41
+ const inputAttrs : string[] = [ 'class="sk-number-input-field"', 'type="number"' ];
42
+
43
+ const passthroughString = [ 'value', 'min', 'max', 'step', 'name', 'placeholder' ] as const;
44
+ for(const key of passthroughString)
45
+ {
46
+ const val = props[key];
47
+ if(typeof val === 'string')
48
+ {
49
+ inputAttrs.push(`${ key }="${ escapeAttr(val) }"`);
50
+ }
51
+ }
52
+
53
+ const passthroughBool = [ 'disabled', 'readonly', 'required' ] as const;
54
+ for(const key of passthroughBool)
55
+ {
56
+ if(props[key] === true) { inputAttrs.push(key); }
57
+ }
58
+
59
+ const inputEl = `<input ${ inputAttrs.join(' ') } />`;
60
+
61
+ return `<div class="${ escapeAttr(wrapperClasses) }">${ inputEl }</div>`;
62
+ }
63
+
64
+ //----------------------------------------------------------------------------------------------------------------------
@@ -0,0 +1,31 @@
1
+ //----------------------------------------------------------------------------------------------------------------------
2
+ // Page Static Helper
3
+ //
4
+ // Thin typed wrapper over the generic render() core. Emits a class-API <div> with sk-page
5
+ // modifier classes derived from props.
6
+ //----------------------------------------------------------------------------------------------------------------------
7
+
8
+ import type { PagePanelMode } from '../types';
9
+
10
+ import { render } from '../render';
11
+ import { SPECS } from '../specs';
12
+
13
+ //----------------------------------------------------------------------------------------------------------------------
14
+
15
+ export interface PageStaticProps
16
+ {
17
+ fixedHeader ?: boolean;
18
+ fixedFooter ?: boolean;
19
+ flush ?: boolean;
20
+ sidebarMode ?: PagePanelMode;
21
+ asideMode ?: PagePanelMode;
22
+ }
23
+
24
+ //----------------------------------------------------------------------------------------------------------------------
25
+
26
+ export function page(props : PageStaticProps = {}, children = '') : string
27
+ {
28
+ return render(SPECS.page, props as Record<string, unknown>, children);
29
+ }
30
+
31
+ //----------------------------------------------------------------------------------------------------------------------
@@ -0,0 +1,27 @@
1
+ //----------------------------------------------------------------------------------------------------------------------
2
+ // Pagination Static Helper
3
+ //
4
+ // Thin typed wrapper over the generic render() core. Emits a class-API <nav aria-label="Pagination">
5
+ // with sk-pagination modifier classes derived from props.
6
+ //----------------------------------------------------------------------------------------------------------------------
7
+
8
+ import type { PaginationKind, StaticCustomColors } from '../types';
9
+
10
+ import { render } from '../render';
11
+ import { SPECS } from '../specs';
12
+
13
+ //----------------------------------------------------------------------------------------------------------------------
14
+
15
+ export interface PaginationStaticProps extends StaticCustomColors
16
+ {
17
+ kind ?: PaginationKind;
18
+ }
19
+
20
+ //----------------------------------------------------------------------------------------------------------------------
21
+
22
+ export function pagination(props : PaginationStaticProps = {}, children = '') : string
23
+ {
24
+ return render(SPECS.pagination, props as Record<string, unknown>, children);
25
+ }
26
+
27
+ //----------------------------------------------------------------------------------------------------------------------
@@ -0,0 +1,33 @@
1
+ //----------------------------------------------------------------------------------------------------------------------
2
+ // Panel Static Helper
3
+ //
4
+ // Thin typed wrapper over the generic render() core. Emits a class-API <div> with sk-panel
5
+ // modifier classes derived from props.
6
+ //----------------------------------------------------------------------------------------------------------------------
7
+
8
+ import type { PanelCorner, PanelKind, PanelSize, StaticCustomColors } from '../types';
9
+
10
+ import { render } from '../render';
11
+ import { SPECS } from '../specs';
12
+
13
+ //----------------------------------------------------------------------------------------------------------------------
14
+
15
+ export interface PanelStaticProps extends StaticCustomColors
16
+ {
17
+ kind ?: PanelKind;
18
+ size ?: PanelSize;
19
+ showDecoration ?: boolean;
20
+ noBorder ?: boolean;
21
+ noDecoration ?: boolean;
22
+ corners ?: PanelCorner[];
23
+ decorationCorner ?: PanelCorner;
24
+ }
25
+
26
+ //----------------------------------------------------------------------------------------------------------------------
27
+
28
+ export function panel(props : PanelStaticProps = {}, children = '') : string
29
+ {
30
+ return render(SPECS.panel, props as Record<string, unknown>, children);
31
+ }
32
+
33
+ //----------------------------------------------------------------------------------------------------------------------
@@ -0,0 +1,31 @@
1
+ //----------------------------------------------------------------------------------------------------------------------
2
+ // Progress Static Helper
3
+ //
4
+ // Thin typed wrapper over the generic render() core. Emits a class-API void <progress /> with
5
+ // sk-progress modifier classes derived from props.
6
+ //----------------------------------------------------------------------------------------------------------------------
7
+
8
+ import type { ComponentKind, ProgressSize } from '../types';
9
+
10
+ import { render } from '../render';
11
+ import { SPECS } from '../specs';
12
+
13
+ //----------------------------------------------------------------------------------------------------------------------
14
+
15
+ export interface ProgressStaticProps
16
+ {
17
+ kind ?: ComponentKind;
18
+ size ?: ProgressSize;
19
+ indeterminate ?: boolean;
20
+ value ?: number | null;
21
+ max ?: number;
22
+ }
23
+
24
+ //----------------------------------------------------------------------------------------------------------------------
25
+
26
+ export function progress(props : ProgressStaticProps = {}, children = '') : string
27
+ {
28
+ return render(SPECS.progress, props as Record<string, unknown>, children);
29
+ }
30
+
31
+ //----------------------------------------------------------------------------------------------------------------------
@@ -0,0 +1,53 @@
1
+ //----------------------------------------------------------------------------------------------------------------------
2
+ // Radio Static Helper
3
+ //
4
+ // Emits a compound <label class="sk-radio"><input type="radio" name="..." value="..." />
5
+ // <span class="sk-radio-dot"></span><span class="sk-radio-label">children</span></label>
6
+ // structure for pure-CSS usage.
7
+ //----------------------------------------------------------------------------------------------------------------------
8
+
9
+ import type { ComponentKind, ComponentSize } from '../types';
10
+
11
+ import { composeClasses } from '../classes';
12
+ import { escapeAttr } from '../escape';
13
+
14
+ //----------------------------------------------------------------------------------------------------------------------
15
+
16
+ export interface RadioStaticProps
17
+ {
18
+ kind ?: ComponentKind;
19
+ size ?: ComponentSize;
20
+ name ?: string;
21
+ value ?: string;
22
+ checked ?: boolean;
23
+ disabled ?: boolean;
24
+ required ?: boolean;
25
+ }
26
+
27
+ //----------------------------------------------------------------------------------------------------------------------
28
+
29
+ export function radio(props : RadioStaticProps = {}, children = '') : string
30
+ {
31
+ const classes = composeClasses({ base: 'sk-radio', kind: true, size: true }, props as Record<string, unknown>);
32
+
33
+ const inputAttrs : string[] = [ 'type="radio"' ];
34
+ if(props.name)
35
+ {
36
+ inputAttrs.push(`name="${ escapeAttr(props.name) }"`);
37
+ }
38
+ if(props.value !== undefined)
39
+ {
40
+ inputAttrs.push(`value="${ escapeAttr(props.value) }"`);
41
+ }
42
+ if(props.checked === true) { inputAttrs.push('checked'); }
43
+ if(props.disabled === true) { inputAttrs.push('disabled'); }
44
+ if(props.required === true) { inputAttrs.push('required'); }
45
+
46
+ const inputEl = `<input ${ inputAttrs.join(' ') } />`;
47
+ const dotEl = `<span class="sk-radio-dot"></span>`;
48
+ const labelEl = `<span class="sk-radio-label">${ children }</span>`;
49
+
50
+ return `<label class="${ escapeAttr(classes) }">${ inputEl }${ dotEl }${ labelEl }</label>`;
51
+ }
52
+
53
+ //----------------------------------------------------------------------------------------------------------------------
@@ -0,0 +1,51 @@
1
+ //----------------------------------------------------------------------------------------------------------------------
2
+ // Select Static Helper
3
+ //
4
+ // Emits a non-void <select class="sk-select">children</select> where children are option elements
5
+ // composed by the caller. Passthrough attrs: name, id; booleans: disabled, required.
6
+ //----------------------------------------------------------------------------------------------------------------------
7
+
8
+ import type { ComponentKind, ComponentSize } from '../types';
9
+
10
+ import { composeClasses } from '../classes';
11
+ import { escapeAttr } from '../escape';
12
+
13
+ //----------------------------------------------------------------------------------------------------------------------
14
+
15
+ export interface SelectStaticProps
16
+ {
17
+ kind ?: ComponentKind;
18
+ size ?: ComponentSize;
19
+ name ?: string;
20
+ id ?: string;
21
+ disabled ?: boolean;
22
+ required ?: boolean;
23
+ }
24
+
25
+ //----------------------------------------------------------------------------------------------------------------------
26
+
27
+ export function select(props : SelectStaticProps = {}, children = '') : string
28
+ {
29
+ const classes = composeClasses({ base: 'sk-select', kind: true, size: true }, props as Record<string, unknown>);
30
+ const attrs : string[] = [ `class="${ escapeAttr(classes) }"` ];
31
+
32
+ const passthroughString = [ 'name', 'id' ] as const;
33
+ for(const key of passthroughString)
34
+ {
35
+ const val = props[key];
36
+ if(typeof val === 'string')
37
+ {
38
+ attrs.push(`${ key }="${ escapeAttr(val) }"`);
39
+ }
40
+ }
41
+
42
+ const passthroughBool = [ 'disabled', 'required' ] as const;
43
+ for(const key of passthroughBool)
44
+ {
45
+ if(props[key] === true) { attrs.push(key); }
46
+ }
47
+
48
+ return `<select ${ attrs.join(' ') }>${ children }</select>`;
49
+ }
50
+
51
+ //----------------------------------------------------------------------------------------------------------------------
@@ -0,0 +1,85 @@
1
+ //----------------------------------------------------------------------------------------------------------------------
2
+ // Sidebar Static Helper
3
+ //
4
+ // Emits the full sidebar DOM structure matching the Vue component's rendered output:
5
+ // <aside class="sk-sidebar sk-<kind> [sk-sidebar-right] [sk-dense]">
6
+ // <div class="sk-panel sk-<kind> sk-md sk-cut-<corner> sk-decoration-<corner> sk-sidebar-panel">
7
+ // <div class="sk-panel-scroll-content">
8
+ // <nav class="sk-sidebar-nav">children</nav>
9
+ // </div>
10
+ // </div>
11
+ // </aside>
12
+ //
13
+ // The inner panel corner and decoration corner are computed from the `side` prop:
14
+ // left (default) → bottom-right corner + decoration
15
+ // right → bottom-left corner + decoration
16
+ //
17
+ // The panel always uses size 'md' (SkPanel's default) since SkSidebar does not expose a size
18
+ // prop and passes none to SkPanel.
19
+ //----------------------------------------------------------------------------------------------------------------------
20
+
21
+ import type { SidebarKind, SidebarSide, StaticCustomColors } from '../types';
22
+
23
+ import { escapeAttr } from '../escape';
24
+
25
+ //----------------------------------------------------------------------------------------------------------------------
26
+
27
+ export interface SidebarStaticProps extends StaticCustomColors
28
+ {
29
+ kind ?: SidebarKind;
30
+ side ?: SidebarSide;
31
+ dense ?: boolean;
32
+
33
+ /** CSS width of the sidebar (not used for class output; here for completeness). */
34
+ width ?: string;
35
+ }
36
+
37
+ //----------------------------------------------------------------------------------------------------------------------
38
+
39
+ export function sidebar(props : SidebarStaticProps = {}, children = '') : string
40
+ {
41
+ const kind = props.kind ?? 'neutral';
42
+ const side = props.side ?? 'left';
43
+
44
+ // --- aside classes (mirrors SkSidebar's computed `classes`) ---
45
+ const asideParts : string[] = [ 'sk-sidebar', `sk-${ kind }` ];
46
+ if(side === 'right') { asideParts.push('sk-sidebar-right'); }
47
+ if(props.dense === true) { asideParts.push('sk-dense'); }
48
+
49
+ // --- inner panel corner + decoration (mirrors SkSidebar's panelCorners + panelDecorationCorner) ---
50
+ const panelCorner = side === 'right' ? 'bottom-left' : 'bottom-right';
51
+
52
+ // Panel classes match SkPanel's computed `classes` with:
53
+ // kind = sidebar kind, size = 'md' (panel default), corners = [panelCorner],
54
+ // decorationCorner = panelCorner, plus the sidebar-specific sk-sidebar-panel override
55
+ const panelParts : string[] = [
56
+ 'sk-panel',
57
+ `sk-${ kind }`,
58
+ 'sk-md', // SkPanel size default
59
+ `sk-cut-${ panelCorner }`,
60
+ `sk-decoration-${ panelCorner }`,
61
+ 'sk-sidebar-panel', // extra class SkSidebar adds to SkPanel
62
+ ];
63
+
64
+ const asideAttrs = `class="${ escapeAttr(asideParts.join(' ')) }"`;
65
+ const panelAttrs = `class="${ escapeAttr(panelParts.join(' ')) }"`;
66
+
67
+ // Custom color styles go on the aside element (matching SkSidebar's sidebarStyles)
68
+ const asideStyleParts : string[] = [];
69
+ if(typeof props.baseColor === 'string')
70
+ {
71
+ asideStyleParts.push(`--sk-sidebar-color-base: ${ escapeAttr(props.baseColor) };`);
72
+ }
73
+
74
+ const asideStyle = asideStyleParts.length > 0
75
+ ? ` style="${ asideStyleParts.join(' ') }"`
76
+ : '';
77
+
78
+ const inner = `<div class="sk-panel-scroll-content"><nav class="sk-sidebar-nav">${ children }</nav></div>`;
79
+
80
+ return `<aside ${ asideAttrs }${ asideStyle }>`
81
+ + `<div ${ panelAttrs }>${ inner }</div>`
82
+ + '</aside>';
83
+ }
84
+
85
+ //----------------------------------------------------------------------------------------------------------------------
@@ -0,0 +1,66 @@
1
+ //----------------------------------------------------------------------------------------------------------------------
2
+ // Skeleton Static Helper
3
+ //
4
+ // Emits the skeleton DOM structure matching the Vue component's rendered output:
5
+ // <div class="sk-skeleton sk-<variant> [sk-<animation>] [sk-custom-corners]" [style="..."]>
6
+ //
7
+ // Class families match Vue exactly:
8
+ // variant → sk-text / sk-rectangular / sk-circular / sk-square (sk-${variant})
9
+ // animation → sk-shimmer / sk-pulse (sk-${animation})
10
+ // omitted when animation === 'none'
11
+ //
12
+ // Inline style: `width` and `height` props are forwarded as CSS if provided, matching Vue's
13
+ // computed `styles`. Pass width='100%' explicitly (Vue's default) for parity tests. The
14
+ // static helper does NOT apply automatic height-from-width for circular/square — that logic
15
+ // requires knowing both props at render time, and a static helper consumer should pass both
16
+ // when needed.
17
+ //----------------------------------------------------------------------------------------------------------------------
18
+
19
+ import { escapeAttr } from '../escape';
20
+
21
+ //----------------------------------------------------------------------------------------------------------------------
22
+
23
+ export type SkeletonVariant = 'text' | 'circular' | 'rectangular' | 'square';
24
+ export type SkeletonAnimation = 'shimmer' | 'pulse' | 'none';
25
+
26
+ export interface SkeletonStaticProps
27
+ {
28
+ variant ?: SkeletonVariant;
29
+ animation ?: SkeletonAnimation;
30
+
31
+ /** CSS width value, e.g. '200px', '100%'. Emitted as inline style when set. */
32
+ width ?: string;
33
+
34
+ /** CSS height value. Emitted as inline style when set. */
35
+ height ?: string;
36
+ }
37
+
38
+ //----------------------------------------------------------------------------------------------------------------------
39
+
40
+ export function skeleton(props : SkeletonStaticProps = {}) : string
41
+ {
42
+ const variant = props.variant ?? 'text';
43
+ const animation = props.animation ?? 'shimmer';
44
+
45
+ const classes : string[] = [ 'sk-skeleton', `sk-${ variant }` ];
46
+ if(animation !== 'none') { classes.push(`sk-${ animation }`); }
47
+
48
+ const attrs : string[] = [ `class="${ escapeAttr(classes.join(' ')) }"` ];
49
+
50
+ // Inline style: forward width/height when provided.
51
+ // For circular/square variants, height = width when only width is set — mirrors Vue's styles computed.
52
+ const styleParts : string[] = [];
53
+ const resolvedHeight = props.height
54
+ ?? ((variant === 'circular' || variant === 'square') && props.width ? props.width : undefined);
55
+
56
+ if(typeof props.width === 'string') { styleParts.push(`width: ${ escapeAttr(props.width) };`); }
57
+ if(typeof resolvedHeight === 'string') { styleParts.push(`height: ${ escapeAttr(resolvedHeight) };`); }
58
+ if(styleParts.length > 0)
59
+ {
60
+ attrs.push(`style="${ styleParts.join(' ') }"`);
61
+ }
62
+
63
+ return `<div ${ attrs.join(' ') }></div>`;
64
+ }
65
+
66
+ //----------------------------------------------------------------------------------------------------------------------
@@ -0,0 +1,50 @@
1
+ //----------------------------------------------------------------------------------------------------------------------
2
+ // Slider Static Helper
3
+ //
4
+ // Emits a void <input class="sk-slider" type="range" /> with passthrough attrs for
5
+ // min, max, step, value, name. All numeric-in-usage props are accepted as strings for
6
+ // clean HTML attribute emission.
7
+ //----------------------------------------------------------------------------------------------------------------------
8
+
9
+ import type { ComponentKind, ComponentSize } from '../types';
10
+
11
+ import { composeClasses } from '../classes';
12
+ import { escapeAttr } from '../escape';
13
+
14
+ //----------------------------------------------------------------------------------------------------------------------
15
+
16
+ export interface SliderStaticProps
17
+ {
18
+ kind ?: ComponentKind;
19
+ size ?: ComponentSize;
20
+ min ?: string;
21
+ max ?: string;
22
+ step ?: string;
23
+ value ?: string;
24
+ name ?: string;
25
+ disabled ?: boolean;
26
+ }
27
+
28
+ //----------------------------------------------------------------------------------------------------------------------
29
+
30
+ export function slider(props : SliderStaticProps = {}) : string
31
+ {
32
+ const classes = composeClasses({ base: 'sk-slider', kind: true, size: true }, props as Record<string, unknown>);
33
+ const attrs : string[] = [ `class="${ escapeAttr(classes) }"`, 'type="range"' ];
34
+
35
+ const passthroughString = [ 'min', 'max', 'step', 'value', 'name' ] as const;
36
+ for(const key of passthroughString)
37
+ {
38
+ const val = props[key];
39
+ if(typeof val === 'string')
40
+ {
41
+ attrs.push(`${ key }="${ escapeAttr(val) }"`);
42
+ }
43
+ }
44
+
45
+ if(props.disabled === true) { attrs.push('disabled'); }
46
+
47
+ return `<input ${ attrs.join(' ') } />`;
48
+ }
49
+
50
+ //----------------------------------------------------------------------------------------------------------------------