@skewedaspect/sleekspace-ui 0.8.1 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/Dropdown/SkDropdown.vue.d.ts +9 -1
- package/dist/components/Dropdown/types.d.ts +2 -1
- package/dist/components/NavBar/SkNavBar.vue.d.ts +9 -1
- package/dist/components/NavBar/context.d.ts +2 -0
- package/dist/components/NavBar/types.d.ts +5 -1
- package/dist/components/Page/SkPage.vue.d.ts +9 -0
- package/dist/components/ScrollArea/SkScrollArea.vue.d.ts +105 -4
- package/dist/composables/useCustomColors.d.ts +18 -56
- package/{src → dist}/global.d.ts +6 -2
- package/dist/sleekspace-ui.css +4253 -1251
- package/dist/sleekspace-ui.es.js +204 -109
- package/dist/sleekspace-ui.umd.js +204 -109
- package/dist/static/classes.d.ts +18 -0
- package/dist/static/components/alert.d.ts +12 -0
- package/dist/static/components/avatar.d.ts +9 -0
- package/dist/static/components/breadcrumbs.d.ts +6 -0
- package/dist/static/components/button.d.ts +13 -0
- package/dist/static/components/card.d.ts +5 -0
- package/dist/static/components/checkbox.d.ts +10 -0
- package/dist/static/components/colorPicker.d.ts +8 -0
- package/dist/static/components/divider.d.ts +8 -0
- package/dist/static/components/dropdown.d.ts +8 -0
- package/dist/static/components/field.d.ts +15 -0
- package/dist/static/components/group.d.ts +5 -0
- package/dist/static/components/input.d.ts +14 -0
- package/dist/static/components/navBar.d.ts +16 -0
- package/dist/static/components/numberInput.d.ts +15 -0
- package/dist/static/components/page.d.ts +9 -0
- package/dist/static/components/pagination.d.ts +5 -0
- package/dist/static/components/panel.d.ts +11 -0
- package/dist/static/components/progress.d.ts +9 -0
- package/dist/static/components/radio.d.ts +11 -0
- package/dist/static/components/select.d.ts +10 -0
- package/dist/static/components/sidebar.d.ts +9 -0
- package/dist/static/components/skeleton.d.ts +11 -0
- package/dist/static/components/slider.d.ts +12 -0
- package/dist/static/components/spinner.d.ts +12 -0
- package/dist/static/components/switchInput.d.ts +10 -0
- package/dist/static/components/table.d.ts +12 -0
- package/dist/static/components/tag.d.ts +8 -0
- package/dist/static/components/tagsInput.d.ts +7 -0
- package/dist/static/components/textarea.d.ts +12 -0
- package/dist/static/components/toolbar.d.ts +12 -0
- package/dist/static/components/tooltip.d.ts +7 -0
- package/dist/static/escape.d.ts +2 -0
- package/dist/static/index.cjs.js +1 -0
- package/dist/static/index.d.ts +68 -0
- package/dist/static/index.es.js +732 -0
- package/dist/static/render.d.ts +12 -0
- package/dist/static/specs.d.ts +2 -0
- package/dist/static/types.d.ts +43 -0
- package/dist/tokens.css +322 -0
- package/dist/types/index.d.ts +36 -0
- package/docs/guides/installation.md +8 -2
- package/docs/guides/pure-css/_meta.yaml +8 -0
- package/docs/guides/pure-css/class-api.md +1070 -0
- package/docs/guides/pure-css/custom-elements.md +574 -0
- package/docs/guides/pure-css/index.md +86 -0
- package/docs/guides/pure-css/limitations.md +152 -0
- package/docs/guides/pure-css/static-helpers.md +1203 -0
- package/llms-full.txt +3736 -261
- package/package.json +16 -5
- package/src/components/Card/SkCard.vue +1 -0
- package/src/components/ContextMenu/SkContextMenuRadioGroup.vue +4 -1
- package/src/components/Dropdown/SkDropdown.vue +20 -3
- package/src/components/Dropdown/SkDropdownRadioGroup.vue +4 -1
- package/src/components/Dropdown/types.ts +2 -1
- package/src/components/NavBar/SkNavBar.vue +14 -4
- package/src/components/NavBar/context.ts +4 -2
- package/src/components/NavBar/types.ts +6 -1
- package/src/components/Page/SkPage.vue +11 -0
- package/src/components/Panel/SkPanel.vue +2 -1
- package/src/components/ScrollArea/SkScrollArea.vue +78 -5
- package/src/components/TreeView/SkTreeView.vue +7 -2
- package/src/composables/useCustomColors.ts +86 -77
- package/src/composables/usePortalContext.test.ts +0 -2
- package/src/shims.d.ts +10 -0
- package/src/static/__tests__/parity.test.ts +717 -0
- package/src/static/__tests__/parityHarness.test.ts +98 -0
- package/src/static/__tests__/parityHarness.ts +260 -0
- package/src/static/classes.test.ts +82 -0
- package/src/static/classes.ts +111 -0
- package/src/static/components/__tests__/helpers.test.ts +837 -0
- package/src/static/components/alert.ts +117 -0
- package/src/static/components/avatar.ts +86 -0
- package/src/static/components/breadcrumbs.ts +28 -0
- package/src/static/components/button.ts +75 -0
- package/src/static/components/card.ts +27 -0
- package/src/static/components/checkbox.ts +48 -0
- package/src/static/components/colorPicker.ts +45 -0
- package/src/static/components/divider.ts +39 -0
- package/src/static/components/dropdown.ts +36 -0
- package/src/static/components/field.ts +86 -0
- package/src/static/components/group.ts +27 -0
- package/src/static/components/input.ts +55 -0
- package/src/static/components/navBar.ts +94 -0
- package/src/static/components/numberInput.ts +64 -0
- package/src/static/components/page.ts +31 -0
- package/src/static/components/pagination.ts +27 -0
- package/src/static/components/panel.ts +33 -0
- package/src/static/components/progress.ts +31 -0
- package/src/static/components/radio.ts +53 -0
- package/src/static/components/select.ts +51 -0
- package/src/static/components/sidebar.ts +85 -0
- package/src/static/components/skeleton.ts +66 -0
- package/src/static/components/slider.ts +50 -0
- package/src/static/components/spinner.ts +94 -0
- package/src/static/components/switchInput.ts +49 -0
- package/src/static/components/table.ts +88 -0
- package/src/static/components/tag.ts +76 -0
- package/src/static/components/tagsInput.ts +35 -0
- package/src/static/components/textarea.ts +53 -0
- package/src/static/components/toolbar.ts +74 -0
- package/src/static/components/tooltip.ts +29 -0
- package/src/static/escape.test.ts +53 -0
- package/src/static/escape.ts +28 -0
- package/src/static/generated/defaults.ts +378 -0
- package/src/static/generated/propTypes.ts +425 -0
- package/src/static/index.ts +116 -0
- package/src/static/render.test.ts +83 -0
- package/src/static/render.ts +76 -0
- package/src/static/specs.test.ts +58 -0
- package/src/static/specs.ts +230 -0
- package/src/static/types.ts +176 -0
- package/src/styles/__tests__/testHelpers.ts +97 -0
- package/src/styles/base/_custom-elements.scss +51 -0
- package/src/styles/base/_index.scss +4 -0
- package/src/styles/components/__tests__/componentSelectors.test.ts +2575 -0
- package/src/styles/components/_alert.scss +82 -39
- package/src/styles/components/_avatar.scss +102 -47
- package/src/styles/components/_breadcrumbs.scss +39 -37
- package/src/styles/components/_button.scss +58 -5
- package/src/styles/components/_card.scss +64 -2
- package/src/styles/components/_checkbox.scss +35 -5
- package/src/styles/components/_color-picker.scss +48 -13
- package/src/styles/components/_divider.scss +86 -52
- package/src/styles/components/_dropdown.scss +214 -0
- package/src/styles/components/_field.scss +76 -23
- package/src/styles/components/_group.scss +190 -79
- package/src/styles/components/_index.scss +1 -0
- package/src/styles/components/_input.scss +81 -5
- package/src/styles/components/_menu.scss +1 -1
- package/src/styles/components/_navbar.scss +76 -45
- package/src/styles/components/_number-input.scss +88 -83
- package/src/styles/components/_page.scss +82 -23
- package/src/styles/components/_pagination.scss +240 -212
- package/src/styles/components/_panel.scss +268 -122
- package/src/styles/components/_progress.scss +120 -70
- package/src/styles/components/_radio.scss +35 -5
- package/src/styles/components/_scroll-area.scss +50 -22
- package/src/styles/components/_select.scss +40 -9
- package/src/styles/components/_sidebar.scss +59 -34
- package/src/styles/components/_skeleton.scss +111 -65
- package/src/styles/components/_slider.scss +34 -10
- package/src/styles/components/_spinner.scss +107 -56
- package/src/styles/components/_switch.scss +36 -5
- package/src/styles/components/_table.scss +150 -166
- package/src/styles/components/_tag.scss +244 -154
- package/src/styles/components/_tags-input.scss +46 -12
- package/src/styles/components/_textarea.scss +36 -5
- package/src/styles/components/_toolbar.scss +85 -31
- package/src/styles/components/_tooltip.scss +172 -3
- package/src/styles/mixins/_cut-border.scss +18 -4
- package/src/styles/mixins/_dual-selector.scss +192 -0
- package/src/styles/mixins/_index.scss +1 -0
- package/src/styles/mixins/dualSelector.test.ts +151 -0
- package/src/styles/themes/_colorful.scss +25 -0
- package/src/styles/themes/_greyscale.scss +25 -0
- package/src/styles/themes/_shade-scale.scss +39 -0
- package/src/styles/tokens/_semantic-color-kinds.scss +66 -0
- package/src/{types.ts → types/index.ts} +19 -11
- package/web-types.json +970 -137
- package/dist/composables/useCustomColors.test.d.ts +0 -1
- package/dist/composables/useFocusTrap.test.d.ts +0 -1
- package/dist/composables/usePortalContext.test.d.ts +0 -1
- package/dist/styles/mixins/fluidSize.test.d.ts +0 -1
- package/dist/types.d.ts +0 -29
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
2
|
+
// Alert Static Helper
|
|
3
|
+
//
|
|
4
|
+
// Emits the full alert DOM structure: optional icon container + content wrapper, matching the
|
|
5
|
+
// Vue component's rendered output. Icon is auto-selected by kind for the four feedback kinds
|
|
6
|
+
// (info, success, warning, danger). Pass `icon: false` to suppress it, or `icon: '<html>'`
|
|
7
|
+
// for a custom icon.
|
|
8
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
9
|
+
|
|
10
|
+
import type { AlertKind, StaticCustomColors } from '../types';
|
|
11
|
+
|
|
12
|
+
import { composeClasses } from '../classes';
|
|
13
|
+
import { escapeAttr } from '../escape';
|
|
14
|
+
|
|
15
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
16
|
+
|
|
17
|
+
// Feedback kinds that have a default icon — mirrors FEEDBACK_KINDS in the Vue component.
|
|
18
|
+
const FEEDBACK_KINDS = new Set([ 'info', 'success', 'warning', 'danger' ]);
|
|
19
|
+
|
|
20
|
+
// Default SVG icons per feedback kind, matching the exact SVG content in SkAlert.vue.
|
|
21
|
+
const DEFAULT_ICONS : Record<string, string>
|
|
22
|
+
= {
|
|
23
|
+
info: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">'
|
|
24
|
+
+ '<circle cx="12" cy="12" r="10"></circle>'
|
|
25
|
+
+ '<line x1="12" y1="16" x2="12" y2="12"></line>'
|
|
26
|
+
+ '<circle cx="12" cy="8" r="0.5" fill="currentColor"></circle>'
|
|
27
|
+
+ '</svg>',
|
|
28
|
+
|
|
29
|
+
success: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">'
|
|
30
|
+
+ '<path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"></path>'
|
|
31
|
+
+ '<polyline points="22 4 12 14.01 9 11.01"></polyline>'
|
|
32
|
+
+ '</svg>',
|
|
33
|
+
|
|
34
|
+
warning: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">'
|
|
35
|
+
+ '<path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z">'
|
|
36
|
+
+ '</path>'
|
|
37
|
+
+ '<line x1="12" y1="9" x2="12" y2="13"></line>'
|
|
38
|
+
+ '<circle cx="12" cy="17" r="0.5" fill="currentColor"></circle>'
|
|
39
|
+
+ '</svg>',
|
|
40
|
+
|
|
41
|
+
danger: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">'
|
|
42
|
+
+ '<circle cx="12" cy="12" r="10"></circle>'
|
|
43
|
+
+ '<line x1="15" y1="9" x2="9" y2="15"></line>'
|
|
44
|
+
+ '<line x1="9" y1="9" x2="15" y2="15"></line>'
|
|
45
|
+
+ '</svg>',
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
49
|
+
|
|
50
|
+
export interface AlertStaticProps extends StaticCustomColors
|
|
51
|
+
{
|
|
52
|
+
kind ?: AlertKind;
|
|
53
|
+
subtle ?: boolean;
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Custom icon HTML string, or `false` to suppress the icon entirely.
|
|
57
|
+
* When omitted (default), a kind-appropriate SVG is shown for feedback kinds
|
|
58
|
+
* (info, success, warning, danger); non-feedback kinds show no icon.
|
|
59
|
+
*/
|
|
60
|
+
icon ?: string | false;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
64
|
+
|
|
65
|
+
export function alert(props : AlertStaticProps = {}, children = '') : string
|
|
66
|
+
{
|
|
67
|
+
const kind = props.kind ?? 'info';
|
|
68
|
+
|
|
69
|
+
// Apply default kind so the class is always emitted (mirrors Vue's withDefaults({ kind: 'info' }))
|
|
70
|
+
const propsWithDefaults = { ...props, kind };
|
|
71
|
+
|
|
72
|
+
const classes = composeClasses(
|
|
73
|
+
{
|
|
74
|
+
base: 'sk-alert',
|
|
75
|
+
kind: true,
|
|
76
|
+
booleanFlags: [ 'subtle' ],
|
|
77
|
+
},
|
|
78
|
+
propsWithDefaults as Record<string, unknown>
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
const attrs : string[] = [ `class="${ escapeAttr(classes) }"`, 'role="alert"' ];
|
|
82
|
+
|
|
83
|
+
// Custom color vars — match the Vue component's useCustomColors('alert', ...) output.
|
|
84
|
+
const styleParts : string[] = [];
|
|
85
|
+
if(typeof props.baseColor === 'string')
|
|
86
|
+
{
|
|
87
|
+
styleParts.push(`--sk-alert-color-base: ${ escapeAttr(props.baseColor) };`);
|
|
88
|
+
}
|
|
89
|
+
if(typeof props.textColor === 'string')
|
|
90
|
+
{
|
|
91
|
+
styleParts.push(`--sk-alert-fg: ${ escapeAttr(props.textColor) };`);
|
|
92
|
+
}
|
|
93
|
+
if(styleParts.length > 0)
|
|
94
|
+
{
|
|
95
|
+
attrs.push(`style="${ styleParts.join(' ') }"`);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Determine icon HTML: explicit false = no icon; explicit string = custom; undefined = auto
|
|
99
|
+
let iconHtml = '';
|
|
100
|
+
if(props.icon !== false)
|
|
101
|
+
{
|
|
102
|
+
const iconContent = typeof props.icon === 'string'
|
|
103
|
+
? props.icon
|
|
104
|
+
: (FEEDBACK_KINDS.has(kind) ? (DEFAULT_ICONS[kind] ?? '') : null);
|
|
105
|
+
|
|
106
|
+
if(iconContent !== null)
|
|
107
|
+
{
|
|
108
|
+
iconHtml = `<div class="sk-alert-icon">${ iconContent }</div>`;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const contentHtml = `<div class="sk-alert-content">${ children }</div>`;
|
|
113
|
+
|
|
114
|
+
return `<div ${ attrs.join(' ') }>${ iconHtml }${ contentHtml }</div>`;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
2
|
+
// Avatar Static Helper
|
|
3
|
+
//
|
|
4
|
+
// Emits the full avatar DOM structure matching the Vue component's rendered output:
|
|
5
|
+
// <div class="sk-avatar sk-<kind> sk-<size>" [style="..."]>
|
|
6
|
+
// <img class="sk-avatar-image" src="..." alt="..."> (when src provided)
|
|
7
|
+
// <span class="sk-avatar-initials">AB</span> (when initials provided, no src)
|
|
8
|
+
// <svg class="sk-avatar-icon" ...>…</svg> (default fallback — no src or initials)
|
|
9
|
+
// </div>
|
|
10
|
+
//
|
|
11
|
+
// Fallback priority matches Vue: src → initials → default SVG icon.
|
|
12
|
+
// No `shape` prop — Vue's SkAvatar has no shape prop; that was a prior helper addition that
|
|
13
|
+
// diverged from Vue's actual API. Removed here to match Vue's class output exactly.
|
|
14
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
15
|
+
|
|
16
|
+
import type { AvatarSize, ComponentKind, StaticCustomColors } from '../types';
|
|
17
|
+
|
|
18
|
+
import { escapeAttr } from '../escape';
|
|
19
|
+
|
|
20
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
21
|
+
|
|
22
|
+
export interface AvatarStaticProps extends StaticCustomColors
|
|
23
|
+
{
|
|
24
|
+
kind ?: ComponentKind;
|
|
25
|
+
size ?: AvatarSize;
|
|
26
|
+
src ?: string;
|
|
27
|
+
alt ?: string;
|
|
28
|
+
initials ?: string;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
32
|
+
|
|
33
|
+
// Default fallback SVG — exact content from SkAvatar.vue's default #icon slot
|
|
34
|
+
const DEFAULT_ICON_PATH = 'M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4'
|
|
35
|
+
+ 'v2h16v-2c0-2.66-5.33-4-8-4z';
|
|
36
|
+
const DEFAULT_ICON_SVG = '<svg class="sk-avatar-icon" viewBox="0 0 24 24" fill="currentColor">'
|
|
37
|
+
+ `<path d="${ DEFAULT_ICON_PATH }"></path>`
|
|
38
|
+
+ '</svg>';
|
|
39
|
+
|
|
40
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
41
|
+
|
|
42
|
+
export function avatar(props : AvatarStaticProps = {}) : string
|
|
43
|
+
{
|
|
44
|
+
const kind = props.kind ?? 'neutral';
|
|
45
|
+
const size = props.size ?? 'md';
|
|
46
|
+
|
|
47
|
+
const classes = [ 'sk-avatar', `sk-${ kind }`, `sk-${ size }` ];
|
|
48
|
+
const attrs : string[] = [ `class="${ escapeAttr(classes.join(' ')) }"` ];
|
|
49
|
+
|
|
50
|
+
// Custom color vars — match Vue's customStyles computed property
|
|
51
|
+
const styleParts : string[] = [];
|
|
52
|
+
if(typeof props.baseColor === 'string')
|
|
53
|
+
{
|
|
54
|
+
styleParts.push(`--sk-avatar-color-base: ${ escapeAttr(props.baseColor) };`);
|
|
55
|
+
}
|
|
56
|
+
if(typeof props.textColor === 'string')
|
|
57
|
+
{
|
|
58
|
+
styleParts.push(`--sk-avatar-fg: ${ escapeAttr(props.textColor) };`);
|
|
59
|
+
}
|
|
60
|
+
if(styleParts.length > 0)
|
|
61
|
+
{
|
|
62
|
+
attrs.push(`style="${ styleParts.join(' ') }"`);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Inner content: image > initials > default icon (matches Vue's v-if / v-else-if / v-else)
|
|
66
|
+
let inner : string;
|
|
67
|
+
if(props.src)
|
|
68
|
+
{
|
|
69
|
+
const alt = props.alt ?? '';
|
|
70
|
+
inner = `<img src="${ escapeAttr(props.src) }" alt="${ escapeAttr(alt) }" class="sk-avatar-image">`;
|
|
71
|
+
}
|
|
72
|
+
else if(props.initials)
|
|
73
|
+
{
|
|
74
|
+
// Truncate to 2 chars, uppercase — matches Vue's displayInitials computed
|
|
75
|
+
const display = props.initials.slice(0, 2).toUpperCase();
|
|
76
|
+
inner = `<span class="sk-avatar-initials">${ escapeAttr(display) }</span>`;
|
|
77
|
+
}
|
|
78
|
+
else
|
|
79
|
+
{
|
|
80
|
+
inner = DEFAULT_ICON_SVG;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return `<div ${ attrs.join(' ') }>${ inner }</div>`;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
2
|
+
// Breadcrumbs Static Helper
|
|
3
|
+
//
|
|
4
|
+
// Thin typed wrapper over the generic render() core. Emits a class-API <nav aria-label="Breadcrumbs">
|
|
5
|
+
// with sk-breadcrumbs modifier classes derived from props.
|
|
6
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
7
|
+
|
|
8
|
+
import type { BreadcrumbsKind, StaticCustomColors } from '../types';
|
|
9
|
+
|
|
10
|
+
import { render } from '../render';
|
|
11
|
+
import { SPECS } from '../specs';
|
|
12
|
+
|
|
13
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
14
|
+
|
|
15
|
+
export interface BreadcrumbsStaticProps extends StaticCustomColors
|
|
16
|
+
{
|
|
17
|
+
kind ?: BreadcrumbsKind;
|
|
18
|
+
separator ?: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
22
|
+
|
|
23
|
+
export function breadcrumbs(props : BreadcrumbsStaticProps = {}, children = '') : string
|
|
24
|
+
{
|
|
25
|
+
return render(SPECS.breadcrumbs, props as Record<string, unknown>, children);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
2
|
+
// Button Static Helper
|
|
3
|
+
//
|
|
4
|
+
// Renders <button> (default) or <a> (when href is provided) with the required chrome-wrapper
|
|
5
|
+
// span. Never renders as a custom element. For router-link use cases, the consumer renders
|
|
6
|
+
// their own <a> with class="sk-button" — this helper emits plain HTML only.
|
|
7
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
8
|
+
|
|
9
|
+
import type { ButtonKind, ButtonSize, ButtonType, ButtonVariant, StaticCustomColors } from '../types';
|
|
10
|
+
|
|
11
|
+
import { composeClasses } from '../classes';
|
|
12
|
+
import { escapeAttr } from '../escape';
|
|
13
|
+
|
|
14
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
15
|
+
|
|
16
|
+
export interface ButtonStaticProps extends StaticCustomColors
|
|
17
|
+
{
|
|
18
|
+
type ?: ButtonType;
|
|
19
|
+
kind ?: ButtonKind;
|
|
20
|
+
variant ?: ButtonVariant;
|
|
21
|
+
size ?: ButtonSize;
|
|
22
|
+
disabled ?: boolean;
|
|
23
|
+
loading ?: boolean;
|
|
24
|
+
pressed ?: boolean;
|
|
25
|
+
dense ?: boolean;
|
|
26
|
+
href ?: string;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
30
|
+
|
|
31
|
+
export function button(props : ButtonStaticProps = {}, children = '') : string
|
|
32
|
+
{
|
|
33
|
+
const classes = composeClasses({
|
|
34
|
+
base: 'sk-button',
|
|
35
|
+
kind: true,
|
|
36
|
+
size: true,
|
|
37
|
+
variant: true,
|
|
38
|
+
booleanFlags: [ 'loading', 'pressed', 'dense' ],
|
|
39
|
+
}, props as Record<string, unknown>);
|
|
40
|
+
|
|
41
|
+
const attrs : string[] = [ `class="${ escapeAttr(classes) }"` ];
|
|
42
|
+
const isAnchor = typeof props.href === 'string';
|
|
43
|
+
|
|
44
|
+
if(isAnchor)
|
|
45
|
+
{
|
|
46
|
+
attrs.push(`href="${ escapeAttr(props.href ?? '') }"`);
|
|
47
|
+
}
|
|
48
|
+
else
|
|
49
|
+
{
|
|
50
|
+
const buttonType = props.type ?? 'button';
|
|
51
|
+
attrs.push(`type="${ escapeAttr(buttonType) }"`);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if(props.disabled)
|
|
55
|
+
{
|
|
56
|
+
attrs.push(isAnchor ? 'aria-disabled="true"' : 'disabled');
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if(props.loading)
|
|
60
|
+
{
|
|
61
|
+
attrs.push('aria-busy="true"');
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if(props.pressed)
|
|
65
|
+
{
|
|
66
|
+
attrs.push('aria-pressed="true"');
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const tag = isAnchor ? 'a' : 'button';
|
|
70
|
+
const inner = `<span class="sk-button-chrome">${ children }</span>`;
|
|
71
|
+
|
|
72
|
+
return `<${ tag } ${ attrs.join(' ') }>${ inner }</${ tag }>`;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
2
|
+
// Card Static Helper
|
|
3
|
+
//
|
|
4
|
+
// Thin typed wrapper over the generic render() core. Emits a class-API <div> with sk-card
|
|
5
|
+
// modifier classes derived from props.
|
|
6
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
7
|
+
|
|
8
|
+
import type { CardKind, StaticCustomColors } from '../types';
|
|
9
|
+
|
|
10
|
+
import { render } from '../render';
|
|
11
|
+
import { SPECS } from '../specs';
|
|
12
|
+
|
|
13
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
14
|
+
|
|
15
|
+
export interface CardStaticProps extends StaticCustomColors
|
|
16
|
+
{
|
|
17
|
+
kind ?: CardKind;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
21
|
+
|
|
22
|
+
export function card(props : CardStaticProps = {}, children = '') : string
|
|
23
|
+
{
|
|
24
|
+
return render(SPECS.card, props as Record<string, unknown>, children);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
2
|
+
// Checkbox Static Helper
|
|
3
|
+
//
|
|
4
|
+
// Emits a compound <label class="sk-checkbox"><input type="checkbox" /><span class="sk-checkbox-box"></span>
|
|
5
|
+
// <span class="sk-checkbox-label">children</span></label> structure for pure-CSS usage. This is
|
|
6
|
+
// the static/SSG-friendly alternative to the Reka UI–based Vue component.
|
|
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 CheckboxStaticProps
|
|
17
|
+
{
|
|
18
|
+
kind ?: ComponentKind;
|
|
19
|
+
size ?: ComponentSize;
|
|
20
|
+
checked ?: boolean;
|
|
21
|
+
disabled ?: boolean;
|
|
22
|
+
required ?: boolean;
|
|
23
|
+
name ?: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
27
|
+
|
|
28
|
+
export function checkbox(props : CheckboxStaticProps = {}, children = '') : string
|
|
29
|
+
{
|
|
30
|
+
const classes = composeClasses({ base: 'sk-checkbox', kind: true, size: true }, props as Record<string, unknown>);
|
|
31
|
+
|
|
32
|
+
const inputAttrs : string[] = [ 'type="checkbox"' ];
|
|
33
|
+
if(props.name)
|
|
34
|
+
{
|
|
35
|
+
inputAttrs.push(`name="${ escapeAttr(props.name) }"`);
|
|
36
|
+
}
|
|
37
|
+
if(props.checked === true) { inputAttrs.push('checked'); }
|
|
38
|
+
if(props.disabled === true) { inputAttrs.push('disabled'); }
|
|
39
|
+
if(props.required === true) { inputAttrs.push('required'); }
|
|
40
|
+
|
|
41
|
+
const inputEl = `<input ${ inputAttrs.join(' ') } />`;
|
|
42
|
+
const boxEl = `<span class="sk-checkbox-box"></span>`;
|
|
43
|
+
const labelEl = `<span class="sk-checkbox-label">${ children }</span>`;
|
|
44
|
+
|
|
45
|
+
return `<label class="${ escapeAttr(classes) }">${ inputEl }${ boxEl }${ labelEl }</label>`;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
2
|
+
// ColorPicker Static Helper
|
|
3
|
+
//
|
|
4
|
+
// Emits a void <input class="sk-color-picker" type="color" /> with passthrough attrs for
|
|
5
|
+
// value and name.
|
|
6
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
7
|
+
|
|
8
|
+
import type { ComponentSize } from '../types';
|
|
9
|
+
|
|
10
|
+
import { composeClasses } from '../classes';
|
|
11
|
+
import { escapeAttr } from '../escape';
|
|
12
|
+
|
|
13
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
14
|
+
|
|
15
|
+
export interface ColorPickerStaticProps
|
|
16
|
+
{
|
|
17
|
+
size ?: ComponentSize;
|
|
18
|
+
value ?: string;
|
|
19
|
+
name ?: string;
|
|
20
|
+
disabled ?: boolean;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
24
|
+
|
|
25
|
+
export function colorPicker(props : ColorPickerStaticProps = {}) : string
|
|
26
|
+
{
|
|
27
|
+
const classes = composeClasses({ base: 'sk-color-picker', size: true }, props as Record<string, unknown>);
|
|
28
|
+
const attrs : string[] = [ `class="${ escapeAttr(classes) }"`, 'type="color"' ];
|
|
29
|
+
|
|
30
|
+
const passthroughString = [ 'value', 'name' ] as const;
|
|
31
|
+
for(const key of passthroughString)
|
|
32
|
+
{
|
|
33
|
+
const val = props[key];
|
|
34
|
+
if(typeof val === 'string')
|
|
35
|
+
{
|
|
36
|
+
attrs.push(`${ key }="${ escapeAttr(val) }"`);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if(props.disabled === true) { attrs.push('disabled'); }
|
|
41
|
+
|
|
42
|
+
return `<input ${ attrs.join(' ') } />`;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
2
|
+
// Divider Static Helper
|
|
3
|
+
//
|
|
4
|
+
// Emits an <hr> element matching the Vue component's rendered output. The orientation class
|
|
5
|
+
// follows Vue's pattern: sk-horizontal / sk-vertical (not sk-orientation-*). Kind and size
|
|
6
|
+
// modifier classes are emitted exactly as Vue does, using the sk-${kind} and sk-${size}
|
|
7
|
+
// families. The aria-orientation attribute is omitted — it's filtered by the parity harness
|
|
8
|
+
// as a reka-ui runtime attribute and has no semantic value in a static context.
|
|
9
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
10
|
+
|
|
11
|
+
import type { ComponentKind, ComponentSize, DividerOrientation, DividerVariant } from '../types';
|
|
12
|
+
|
|
13
|
+
import { escapeAttr } from '../escape';
|
|
14
|
+
|
|
15
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
16
|
+
|
|
17
|
+
export interface DividerStaticProps
|
|
18
|
+
{
|
|
19
|
+
orientation ?: DividerOrientation;
|
|
20
|
+
kind ?: ComponentKind;
|
|
21
|
+
variant ?: DividerVariant;
|
|
22
|
+
size ?: ComponentSize;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
26
|
+
|
|
27
|
+
export function divider(props : DividerStaticProps = {}) : string
|
|
28
|
+
{
|
|
29
|
+
const orientation = props.orientation ?? 'horizontal';
|
|
30
|
+
const kind = props.kind ?? 'neutral';
|
|
31
|
+
const size = props.size ?? 'md';
|
|
32
|
+
|
|
33
|
+
const classes : string[] = [ 'sk-divider', `sk-${ orientation }`, `sk-${ kind }`, `sk-${ size }` ];
|
|
34
|
+
if(props.variant === 'subtle') { classes.push('sk-subtle'); }
|
|
35
|
+
|
|
36
|
+
return `<hr class="${ escapeAttr(classes.join(' ')) }" role="separator">`;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
2
|
+
// Dropdown Static Helper (<details> disclosure)
|
|
3
|
+
//
|
|
4
|
+
// Note: this is the pure-CSS disclosure variant, NOT a menu. The Vue SkDropdown is a menu with
|
|
5
|
+
// focus trap and keyboard navigation; this helper outputs a plain <details>/<summary>
|
|
6
|
+
// disclosure styled to match Sleekspace.
|
|
7
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
8
|
+
|
|
9
|
+
import type { SemanticKind } from '../types';
|
|
10
|
+
|
|
11
|
+
import { composeClasses } from '../classes';
|
|
12
|
+
import { escapeAttr } from '../escape';
|
|
13
|
+
|
|
14
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
15
|
+
|
|
16
|
+
export interface DropdownStaticProps
|
|
17
|
+
{
|
|
18
|
+
summary : string;
|
|
19
|
+
kind ?: SemanticKind;
|
|
20
|
+
size ?: 'sm' | 'md' | 'lg';
|
|
21
|
+
open ?: boolean;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
25
|
+
|
|
26
|
+
export function dropdown(props : DropdownStaticProps, children = '') : string
|
|
27
|
+
{
|
|
28
|
+
const spec = { base: 'sk-dropdown', kind: true, size: true } as const;
|
|
29
|
+
const classes = composeClasses(spec, props as unknown as Record<string, unknown>);
|
|
30
|
+
const attrs : string[] = [ `class="${ escapeAttr(classes) }"` ];
|
|
31
|
+
if(props.open) { attrs.push('open'); }
|
|
32
|
+
|
|
33
|
+
return `<details ${ attrs.join(' ') }><summary>${ escapeAttr(props.summary) }</summary>${ children }</details>`;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
2
|
+
// Field Static Helper
|
|
3
|
+
//
|
|
4
|
+
// Emits the full field DOM structure matching the Vue component's rendered output:
|
|
5
|
+
// <div class="sk-field sk-label-<position> [sk-has-error]">
|
|
6
|
+
// [<label for="<id>" class="sk-field-label">
|
|
7
|
+
// LABEL[<span class="sk-field-required">*</span>]
|
|
8
|
+
// </label>]
|
|
9
|
+
// <div class="sk-field-input-wrapper">CHILDREN</div>
|
|
10
|
+
// [<p id="<id>-description" class="sk-field-description">DESCRIPTION</p>]
|
|
11
|
+
// [<p id="<id>-error" class="sk-field-error">ERROR</p>]
|
|
12
|
+
// </div>
|
|
13
|
+
//
|
|
14
|
+
// Label position defaults to 'top' (sk-label-top) — matches Vue's withDefaults({ labelPosition: 'top' }).
|
|
15
|
+
// The sk-field-input-wrapper div is always emitted, wrapping the children slot.
|
|
16
|
+
//
|
|
17
|
+
// The `id` prop mirrors Vue's `id` prop — when provided it is used for the label `for` attribute
|
|
18
|
+
// and the description/error paragraph IDs, enabling DOM-accurate parity tests. When omitted, the
|
|
19
|
+
// label `for` and paragraph IDs are not emitted (Vue auto-generates them at runtime).
|
|
20
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
21
|
+
|
|
22
|
+
import type { FieldLabelPosition } from '../types';
|
|
23
|
+
|
|
24
|
+
import { escapeAttr } from '../escape';
|
|
25
|
+
|
|
26
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
27
|
+
|
|
28
|
+
export interface FieldStaticProps
|
|
29
|
+
{
|
|
30
|
+
label ?: string;
|
|
31
|
+
description ?: string;
|
|
32
|
+
error ?: string;
|
|
33
|
+
required ?: boolean;
|
|
34
|
+
labelPosition ?: FieldLabelPosition;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Explicit field ID — forwarded to label `for` and description/error `id` attributes.
|
|
38
|
+
* Mirrors Vue's `id` prop. When omitted, Vue auto-generates the ID and the static helper
|
|
39
|
+
* skips those attributes (avoid parity tests without an explicit `id`).
|
|
40
|
+
*/
|
|
41
|
+
id ?: string;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
45
|
+
|
|
46
|
+
export function field(props : FieldStaticProps = {}, children = '') : string
|
|
47
|
+
{
|
|
48
|
+
const labelPosition = props.labelPosition ?? 'top';
|
|
49
|
+
|
|
50
|
+
const classes : string[] = [ 'sk-field', `sk-label-${ labelPosition }` ];
|
|
51
|
+
if(props.error) { classes.push('sk-has-error'); }
|
|
52
|
+
|
|
53
|
+
const attrs = `class="${ escapeAttr(classes.join(' ')) }"`;
|
|
54
|
+
|
|
55
|
+
// Label element (only when label prop is set)
|
|
56
|
+
let labelHtml = '';
|
|
57
|
+
if(props.label)
|
|
58
|
+
{
|
|
59
|
+
const forAttr = props.id ? ` for="${ escapeAttr(props.id) }"` : '';
|
|
60
|
+
const requiredSpan = props.required ? '<span class="sk-field-required">*</span>' : '';
|
|
61
|
+
labelHtml = `<label${ forAttr } class="sk-field-label">${ escapeAttr(props.label) }${ requiredSpan }</label>`;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Input wrapper always emitted
|
|
65
|
+
const wrapperHtml = `<div class="sk-field-input-wrapper">${ children }</div>`;
|
|
66
|
+
|
|
67
|
+
// Description (only when set and no error)
|
|
68
|
+
let descriptionHtml = '';
|
|
69
|
+
if(props.description && !props.error)
|
|
70
|
+
{
|
|
71
|
+
const idAttr = props.id ? ` id="${ escapeAttr(props.id) }-description"` : '';
|
|
72
|
+
descriptionHtml = `<p${ idAttr } class="sk-field-description">${ escapeAttr(props.description) }</p>`;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Error (only when set)
|
|
76
|
+
let errorHtml = '';
|
|
77
|
+
if(props.error)
|
|
78
|
+
{
|
|
79
|
+
const idAttr = props.id ? ` id="${ escapeAttr(props.id) }-error"` : '';
|
|
80
|
+
errorHtml = `<p${ idAttr } class="sk-field-error">${ escapeAttr(props.error) }</p>`;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return `<div ${ attrs }>${ labelHtml }${ wrapperHtml }${ descriptionHtml }${ errorHtml }</div>`;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
2
|
+
// Group Static Helper
|
|
3
|
+
//
|
|
4
|
+
// Thin typed wrapper over the generic render() core. Emits a class-API <div> with sk-group
|
|
5
|
+
// modifier classes derived from props.
|
|
6
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
7
|
+
|
|
8
|
+
import type { GroupOrientation } from '../types';
|
|
9
|
+
|
|
10
|
+
import { render } from '../render';
|
|
11
|
+
import { SPECS } from '../specs';
|
|
12
|
+
|
|
13
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
14
|
+
|
|
15
|
+
export interface GroupStaticProps
|
|
16
|
+
{
|
|
17
|
+
orientation ?: GroupOrientation;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
21
|
+
|
|
22
|
+
export function group(props : GroupStaticProps = {}, children = '') : string
|
|
23
|
+
{
|
|
24
|
+
return render(SPECS.group, props as Record<string, unknown>, children);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
//----------------------------------------------------------------------------------------------------------------------
|