@ktbsh/ui 0.1.0 → 0.3.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/README.md +16 -7
- package/dist/custom-elements.json +155 -0
- package/dist/index.d.ts +5 -1
- package/dist/index.js +5 -1
- package/dist/react/preset-toggle.d.ts +18 -0
- package/dist/react/preset-toggle.js +30 -0
- package/dist/react/scroll-top.d.ts +20 -0
- package/dist/react/scroll-top.js +30 -0
- package/dist/react/theme-toggle.d.ts +18 -0
- package/dist/react/theme-toggle.js +30 -0
- package/dist/react/toggle-group.d.ts +17 -0
- package/dist/react/toggle-group.js +30 -0
- package/dist/themes/dark.css +1 -1
- package/dist/themes/light.css +1 -1
- package/dist/themes/terminal/dark.css +52 -0
- package/dist/themes/terminal/light.css +53 -0
- package/dist/tokens/index.d.ts +5 -1
- package/dist/tokens/index.js +5 -1
- package/dist/tokens/semantic.d.ts +23 -3
- package/dist/tokens/semantic.js +35 -7
- package/dist/vanilla/alert.js +1 -48
- package/dist/vanilla/alert.src.js +1 -1
- package/dist/vanilla/badge.js +1 -48
- package/dist/vanilla/badge.src.js +1 -1
- package/dist/vanilla/box.js +1 -48
- package/dist/vanilla/box.src.js +1 -1
- package/dist/vanilla/breadcrumb.js +1 -48
- package/dist/vanilla/breadcrumb.src.js +1 -1
- package/dist/vanilla/button.js +1 -48
- package/dist/vanilla/button.src.js +1 -1
- package/dist/vanilla/checkbox.js +54 -57
- package/dist/vanilla/checkbox.src.js +1 -1
- package/dist/vanilla/container.js +1 -48
- package/dist/vanilla/container.src.js +1 -1
- package/dist/vanilla/field.js +1 -48
- package/dist/vanilla/field.src.js +1 -1
- package/dist/vanilla/heading.js +1 -48
- package/dist/vanilla/heading.src.js +1 -1
- package/dist/vanilla/input.js +7 -48
- package/dist/vanilla/input.src.js +1 -1
- package/dist/vanilla/label.js +1 -48
- package/dist/vanilla/label.src.js +1 -1
- package/dist/vanilla/link.js +1 -48
- package/dist/vanilla/link.src.js +1 -1
- package/dist/vanilla/modal.js +1 -48
- package/dist/vanilla/modal.src.js +1 -1
- package/dist/vanilla/nav.js +1 -48
- package/dist/vanilla/nav.src.js +1 -1
- package/dist/vanilla/pagination.js +1 -48
- package/dist/vanilla/pagination.src.js +1 -1
- package/dist/vanilla/preset-toggle.d.ts +2 -0
- package/dist/vanilla/preset-toggle.js +72 -0
- package/dist/vanilla/preset-toggle.src.js +271 -0
- package/dist/vanilla/progress.js +1 -48
- package/dist/vanilla/progress.src.js +1 -1
- package/dist/vanilla/radio.js +45 -58
- package/dist/vanilla/radio.src.js +1 -1
- package/dist/vanilla/scroll-top.d.ts +2 -0
- package/dist/vanilla/scroll-top.js +69 -0
- package/dist/vanilla/scroll-top.src.js +251 -0
- package/dist/vanilla/select.js +43 -51
- package/dist/vanilla/select.src.js +1 -1
- package/dist/vanilla/skeleton.js +9 -51
- package/dist/vanilla/skeleton.src.js +1 -1
- package/dist/vanilla/spinner.js +1 -48
- package/dist/vanilla/spinner.src.js +1 -1
- package/dist/vanilla/stack.js +1 -48
- package/dist/vanilla/stack.src.js +1 -1
- package/dist/vanilla/switch.js +58 -67
- package/dist/vanilla/switch.src.js +1 -1
- package/dist/vanilla/tab-panel.js +1 -48
- package/dist/vanilla/tab-panel.src.js +1 -1
- package/dist/vanilla/tab.js +1 -48
- package/dist/vanilla/tab.src.js +1 -1
- package/dist/vanilla/tabs.js +1 -48
- package/dist/vanilla/tabs.src.js +1 -1
- package/dist/vanilla/text.js +1 -48
- package/dist/vanilla/text.src.js +1 -1
- package/dist/vanilla/textarea.js +7 -48
- package/dist/vanilla/textarea.src.js +1 -1
- package/dist/vanilla/theme-toggle.d.ts +2 -0
- package/dist/vanilla/theme-toggle.js +72 -0
- package/dist/vanilla/theme-toggle.src.js +242 -0
- package/dist/vanilla/toast.js +1 -48
- package/dist/vanilla/toast.src.js +1 -1
- package/dist/vanilla/toggle-group.d.ts +2 -0
- package/dist/vanilla/toggle-group.js +19 -0
- package/dist/vanilla/toggle-group.src.js +215 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -49,8 +49,10 @@ dist/
|
|
|
49
49
|
| `@ktbsh/ui` | Tokens helpers + shared types |
|
|
50
50
|
| `@ktbsh/ui/vanilla/<name>` | Register `kitbash-<name>` custom element |
|
|
51
51
|
| `@ktbsh/ui/react/<name>` | React wrapper (`Kitbash*`) + types |
|
|
52
|
-
| `@ktbsh/ui/themes/light.css` |
|
|
53
|
-
| `@ktbsh/ui/themes/dark.css` |
|
|
52
|
+
| `@ktbsh/ui/themes/light.css` | Default preset light (`:root` default) |
|
|
53
|
+
| `@ktbsh/ui/themes/dark.css` | Default preset dark (`:root[data-theme="dark"]`) |
|
|
54
|
+
| `@ktbsh/ui/themes/terminal/light.css` | Terminal preset light |
|
|
55
|
+
| `@ktbsh/ui/themes/terminal/dark.css` | Terminal preset dark (Matrix night) |
|
|
54
56
|
| `@ktbsh/ui/tokens` | Token API only |
|
|
55
57
|
| `@ktbsh/ui/types` | Shared TypeScript unions |
|
|
56
58
|
| `@ktbsh/ui/custom-elements.json` | Custom Elements Manifest |
|
|
@@ -87,13 +89,20 @@ Load theme CSS in the host app (variables inherit into shadow roots):
|
|
|
87
89
|
```ts
|
|
88
90
|
import '@ktbsh/ui/themes/light.css';
|
|
89
91
|
import '@ktbsh/ui/themes/dark.css';
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
92
|
+
// Optional Matrix-style preset (blog terminal mode):
|
|
93
|
+
import '@ktbsh/ui/themes/terminal/light.css';
|
|
94
|
+
import '@ktbsh/ui/themes/terminal/dark.css';
|
|
95
|
+
import { applyPreset, applyTheme } from '@ktbsh/ui';
|
|
96
|
+
|
|
97
|
+
applyTheme('dark'); // data-theme — light | dark (night)
|
|
98
|
+
applyPreset('terminal'); // data-kb-preset — default | terminal
|
|
99
|
+
// light + default when attributes omitted
|
|
94
100
|
```
|
|
95
101
|
|
|
96
|
-
|
|
102
|
+
Two axes (same idea as the personal blog): **theme** (light/dark) × **preset** (default/terminal).
|
|
103
|
+
Components use only semantic vars such as `var(--kb-color-accent-default)`, **inherited from document** theme CSS.
|
|
104
|
+
|
|
105
|
+
> **Required:** load theme stylesheets on the app shell (`:root`). We do **not** bake absolute token values onto each component `:host` — that sealed the shadow tree and blocked theme toggles (see `docs/sdk-feedback.md` P0 #0).
|
|
97
106
|
|
|
98
107
|
## Consume
|
|
99
108
|
|
|
@@ -207,6 +207,45 @@
|
|
|
207
207
|
}
|
|
208
208
|
]
|
|
209
209
|
},
|
|
210
|
+
{
|
|
211
|
+
"kind": "javascript-module",
|
|
212
|
+
"path": "vanilla/preset-toggle.js",
|
|
213
|
+
"declarations": [
|
|
214
|
+
{
|
|
215
|
+
"kind": "class",
|
|
216
|
+
"description": "",
|
|
217
|
+
"name": "KitbashPresetToggle",
|
|
218
|
+
"customElement": true,
|
|
219
|
+
"tagName": "kitbash-preset-toggle",
|
|
220
|
+
"attributes": [
|
|
221
|
+
{
|
|
222
|
+
"name": "value",
|
|
223
|
+
"type": {
|
|
224
|
+
"text": "String"
|
|
225
|
+
},
|
|
226
|
+
"default": "\"\""
|
|
227
|
+
},
|
|
228
|
+
{
|
|
229
|
+
"name": "storageKey",
|
|
230
|
+
"type": {
|
|
231
|
+
"text": "String"
|
|
232
|
+
},
|
|
233
|
+
"default": "\"ui-mode\""
|
|
234
|
+
}
|
|
235
|
+
]
|
|
236
|
+
}
|
|
237
|
+
],
|
|
238
|
+
"exports": [
|
|
239
|
+
{
|
|
240
|
+
"kind": "custom-element-definition",
|
|
241
|
+
"name": "kitbash-preset-toggle",
|
|
242
|
+
"declaration": {
|
|
243
|
+
"name": "KitbashPresetToggle",
|
|
244
|
+
"module": "vanilla/preset-toggle.js"
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
]
|
|
248
|
+
},
|
|
210
249
|
{
|
|
211
250
|
"kind": "javascript-module",
|
|
212
251
|
"path": "vanilla/toast.js",
|
|
@@ -564,6 +603,98 @@
|
|
|
564
603
|
}
|
|
565
604
|
]
|
|
566
605
|
},
|
|
606
|
+
{
|
|
607
|
+
"kind": "javascript-module",
|
|
608
|
+
"path": "vanilla/theme-toggle.js",
|
|
609
|
+
"declarations": [
|
|
610
|
+
{
|
|
611
|
+
"kind": "class",
|
|
612
|
+
"description": "",
|
|
613
|
+
"name": "KitbashThemeToggle",
|
|
614
|
+
"customElement": true,
|
|
615
|
+
"tagName": "kitbash-theme-toggle",
|
|
616
|
+
"attributes": [
|
|
617
|
+
{
|
|
618
|
+
"name": "value",
|
|
619
|
+
"type": {
|
|
620
|
+
"text": "String"
|
|
621
|
+
},
|
|
622
|
+
"default": "\"\""
|
|
623
|
+
},
|
|
624
|
+
{
|
|
625
|
+
"name": "storageKey",
|
|
626
|
+
"type": {
|
|
627
|
+
"text": "String"
|
|
628
|
+
},
|
|
629
|
+
"default": "\"theme\""
|
|
630
|
+
}
|
|
631
|
+
]
|
|
632
|
+
}
|
|
633
|
+
],
|
|
634
|
+
"exports": [
|
|
635
|
+
{
|
|
636
|
+
"kind": "custom-element-definition",
|
|
637
|
+
"name": "kitbash-theme-toggle",
|
|
638
|
+
"declaration": {
|
|
639
|
+
"name": "KitbashThemeToggle",
|
|
640
|
+
"module": "vanilla/theme-toggle.js"
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
]
|
|
644
|
+
},
|
|
645
|
+
{
|
|
646
|
+
"kind": "javascript-module",
|
|
647
|
+
"path": "vanilla/scroll-top.js",
|
|
648
|
+
"declarations": [
|
|
649
|
+
{
|
|
650
|
+
"kind": "class",
|
|
651
|
+
"description": "",
|
|
652
|
+
"name": "KitbashScrollTop",
|
|
653
|
+
"customElement": true,
|
|
654
|
+
"tagName": "kitbash-scroll-top",
|
|
655
|
+
"attributes": [
|
|
656
|
+
{
|
|
657
|
+
"name": "visible",
|
|
658
|
+
"type": {
|
|
659
|
+
"text": "Boolean"
|
|
660
|
+
},
|
|
661
|
+
"default": "false"
|
|
662
|
+
},
|
|
663
|
+
{
|
|
664
|
+
"name": "label",
|
|
665
|
+
"type": {
|
|
666
|
+
"text": "String"
|
|
667
|
+
},
|
|
668
|
+
"default": "\"Scroll to top\""
|
|
669
|
+
},
|
|
670
|
+
{
|
|
671
|
+
"name": "caption",
|
|
672
|
+
"type": {
|
|
673
|
+
"text": "String"
|
|
674
|
+
},
|
|
675
|
+
"default": "\"$ top\""
|
|
676
|
+
},
|
|
677
|
+
{
|
|
678
|
+
"name": "behavior",
|
|
679
|
+
"type": {
|
|
680
|
+
"text": "String"
|
|
681
|
+
},
|
|
682
|
+
"default": "\"smooth\""
|
|
683
|
+
}
|
|
684
|
+
]
|
|
685
|
+
}
|
|
686
|
+
],
|
|
687
|
+
"exports": [
|
|
688
|
+
{
|
|
689
|
+
"kind": "custom-element-definition",
|
|
690
|
+
"name": "kitbash-scroll-top",
|
|
691
|
+
"declaration": {
|
|
692
|
+
"name": "KitbashScrollTop",
|
|
693
|
+
"module": "vanilla/scroll-top.js"
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
]
|
|
697
|
+
},
|
|
567
698
|
{
|
|
568
699
|
"kind": "javascript-module",
|
|
569
700
|
"path": "vanilla/switch.js",
|
|
@@ -744,6 +875,30 @@
|
|
|
744
875
|
}
|
|
745
876
|
]
|
|
746
877
|
},
|
|
878
|
+
{
|
|
879
|
+
"kind": "javascript-module",
|
|
880
|
+
"path": "vanilla/toggle-group.js",
|
|
881
|
+
"declarations": [
|
|
882
|
+
{
|
|
883
|
+
"kind": "class",
|
|
884
|
+
"description": "",
|
|
885
|
+
"name": "KitbashToggleGroup",
|
|
886
|
+
"customElement": true,
|
|
887
|
+
"tagName": "kitbash-toggle-group",
|
|
888
|
+
"attributes": []
|
|
889
|
+
}
|
|
890
|
+
],
|
|
891
|
+
"exports": [
|
|
892
|
+
{
|
|
893
|
+
"kind": "custom-element-definition",
|
|
894
|
+
"name": "kitbash-toggle-group",
|
|
895
|
+
"declaration": {
|
|
896
|
+
"name": "KitbashToggleGroup",
|
|
897
|
+
"module": "vanilla/toggle-group.js"
|
|
898
|
+
}
|
|
899
|
+
}
|
|
900
|
+
]
|
|
901
|
+
},
|
|
747
902
|
{
|
|
748
903
|
"kind": "javascript-module",
|
|
749
904
|
"path": "vanilla/stack.js",
|
package/dist/index.d.ts
CHANGED
|
@@ -8,6 +8,10 @@
|
|
|
8
8
|
* Theme CSS (load once in the app shell):
|
|
9
9
|
* import '@ktbsh/ui/themes/light.css'
|
|
10
10
|
* import '@ktbsh/ui/themes/dark.css'
|
|
11
|
+
* import '@ktbsh/ui/themes/terminal/light.css' // optional
|
|
12
|
+
* import '@ktbsh/ui/themes/terminal/dark.css'
|
|
13
|
+
*
|
|
14
|
+
* applyTheme('light'|'dark'); applyPreset('default'|'terminal');
|
|
11
15
|
*/
|
|
12
|
-
export { applyTheme, cssVar, cssVarName, getTheme, type KitbashTheme, type SemanticTokenName, semanticTokens, type TokenValue, } from './tokens/index.ts';
|
|
16
|
+
export { applyPreset, applyTheme, cssVar, cssVarName, getPreset, getTheme, type KitbashPreset, type KitbashTheme, type SemanticTokenName, semanticTokens, type TokenValue, } from './tokens/index.ts';
|
|
13
17
|
export type { KitbashBadgeTone, KitbashButtonVariant, KitbashContainerWidth, KitbashFeedbackTone, KitbashHeadingLevel, KitbashLinkTone, KitbashSize, KitbashSkeletonVariant, KitbashSpace, KitbashStackAlign, KitbashStackDirection, KitbashStackJustify, KitbashTextTone, } from './types/index.ts';
|
package/dist/index.js
CHANGED
|
@@ -8,5 +8,9 @@
|
|
|
8
8
|
* Theme CSS (load once in the app shell):
|
|
9
9
|
* import '@ktbsh/ui/themes/light.css'
|
|
10
10
|
* import '@ktbsh/ui/themes/dark.css'
|
|
11
|
+
* import '@ktbsh/ui/themes/terminal/light.css' // optional
|
|
12
|
+
* import '@ktbsh/ui/themes/terminal/dark.css'
|
|
13
|
+
*
|
|
14
|
+
* applyTheme('light'|'dark'); applyPreset('default'|'terminal');
|
|
11
15
|
*/
|
|
12
|
-
export { applyTheme, cssVar, cssVarName, getTheme, semanticTokens, } from "./tokens/index.js";
|
|
16
|
+
export { applyPreset, applyTheme, cssVar, cssVarName, getPreset, getTheme, semanticTokens, } from "./tokens/index.js";
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
|
|
4
|
+
export interface KitbashPresetToggleProps extends React.HTMLAttributes<HTMLElement> {
|
|
5
|
+
'value'?: string;
|
|
6
|
+
'storageKey'?: string;
|
|
7
|
+
onKitbashChange?: (event: CustomEvent<{ props: Record<string, unknown>; state: Record<string, unknown> }>) => void;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
declare global {
|
|
11
|
+
namespace JSX {
|
|
12
|
+
interface IntrinsicElements {
|
|
13
|
+
'kitbash-preset-toggle': KitbashPresetToggleProps & React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export declare const KitbashPresetToggle: React.ForwardRefExoticComponent<KitbashPresetToggleProps & React.RefAttributes<HTMLElement>>;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import '../vanilla/preset-toggle.js';
|
|
4
|
+
|
|
5
|
+
export const KitbashPresetToggle = React.forwardRef(({ children, onKitbashChange, ...props }, ref) => {
|
|
6
|
+
const innerRef = React.useRef(null);
|
|
7
|
+
|
|
8
|
+
// kitbash-change is a CustomEvent — bridge manually. Native events (onClick, etc.)
|
|
9
|
+
// stay on ...props so React 19 binds them once (no double-fire).
|
|
10
|
+
React.useEffect(() => {
|
|
11
|
+
const el = innerRef.current;
|
|
12
|
+
if (!el || !onKitbashChange) return;
|
|
13
|
+
|
|
14
|
+
const handleCustomChange = (e) => onKitbashChange(e);
|
|
15
|
+
el.addEventListener('kitbash-change', handleCustomChange);
|
|
16
|
+
return () => el.removeEventListener('kitbash-change', handleCustomChange);
|
|
17
|
+
}, [onKitbashChange]);
|
|
18
|
+
|
|
19
|
+
// Callback ref: assign + clear on unmount / ref change (object + function refs).
|
|
20
|
+
const setRefs = React.useCallback((node) => {
|
|
21
|
+
innerRef.current = node;
|
|
22
|
+
if (typeof ref === 'function') {
|
|
23
|
+
ref(node);
|
|
24
|
+
} else if (ref && typeof ref === 'object') {
|
|
25
|
+
ref.current = node;
|
|
26
|
+
}
|
|
27
|
+
}, [ref]);
|
|
28
|
+
|
|
29
|
+
return React.createElement('kitbash-preset-toggle', { ref: setRefs, ...props }, children);
|
|
30
|
+
});
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
|
|
4
|
+
export interface KitbashScrollTopProps extends React.HTMLAttributes<HTMLElement> {
|
|
5
|
+
'visible'?: boolean;
|
|
6
|
+
'label'?: string;
|
|
7
|
+
'caption'?: string;
|
|
8
|
+
'behavior'?: string;
|
|
9
|
+
onKitbashChange?: (event: CustomEvent<{ props: Record<string, unknown>; state: Record<string, unknown> }>) => void;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
declare global {
|
|
13
|
+
namespace JSX {
|
|
14
|
+
interface IntrinsicElements {
|
|
15
|
+
'kitbash-scroll-top': KitbashScrollTopProps & React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export declare const KitbashScrollTop: React.ForwardRefExoticComponent<KitbashScrollTopProps & React.RefAttributes<HTMLElement>>;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import '../vanilla/scroll-top.js';
|
|
4
|
+
|
|
5
|
+
export const KitbashScrollTop = React.forwardRef(({ children, onKitbashChange, ...props }, ref) => {
|
|
6
|
+
const innerRef = React.useRef(null);
|
|
7
|
+
|
|
8
|
+
// kitbash-change is a CustomEvent — bridge manually. Native events (onClick, etc.)
|
|
9
|
+
// stay on ...props so React 19 binds them once (no double-fire).
|
|
10
|
+
React.useEffect(() => {
|
|
11
|
+
const el = innerRef.current;
|
|
12
|
+
if (!el || !onKitbashChange) return;
|
|
13
|
+
|
|
14
|
+
const handleCustomChange = (e) => onKitbashChange(e);
|
|
15
|
+
el.addEventListener('kitbash-change', handleCustomChange);
|
|
16
|
+
return () => el.removeEventListener('kitbash-change', handleCustomChange);
|
|
17
|
+
}, [onKitbashChange]);
|
|
18
|
+
|
|
19
|
+
// Callback ref: assign + clear on unmount / ref change (object + function refs).
|
|
20
|
+
const setRefs = React.useCallback((node) => {
|
|
21
|
+
innerRef.current = node;
|
|
22
|
+
if (typeof ref === 'function') {
|
|
23
|
+
ref(node);
|
|
24
|
+
} else if (ref && typeof ref === 'object') {
|
|
25
|
+
ref.current = node;
|
|
26
|
+
}
|
|
27
|
+
}, [ref]);
|
|
28
|
+
|
|
29
|
+
return React.createElement('kitbash-scroll-top', { ref: setRefs, ...props }, children);
|
|
30
|
+
});
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
|
|
4
|
+
export interface KitbashThemeToggleProps extends React.HTMLAttributes<HTMLElement> {
|
|
5
|
+
'value'?: string;
|
|
6
|
+
'storageKey'?: string;
|
|
7
|
+
onKitbashChange?: (event: CustomEvent<{ props: Record<string, unknown>; state: Record<string, unknown> }>) => void;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
declare global {
|
|
11
|
+
namespace JSX {
|
|
12
|
+
interface IntrinsicElements {
|
|
13
|
+
'kitbash-theme-toggle': KitbashThemeToggleProps & React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export declare const KitbashThemeToggle: React.ForwardRefExoticComponent<KitbashThemeToggleProps & React.RefAttributes<HTMLElement>>;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import '../vanilla/theme-toggle.js';
|
|
4
|
+
|
|
5
|
+
export const KitbashThemeToggle = React.forwardRef(({ children, onKitbashChange, ...props }, ref) => {
|
|
6
|
+
const innerRef = React.useRef(null);
|
|
7
|
+
|
|
8
|
+
// kitbash-change is a CustomEvent — bridge manually. Native events (onClick, etc.)
|
|
9
|
+
// stay on ...props so React 19 binds them once (no double-fire).
|
|
10
|
+
React.useEffect(() => {
|
|
11
|
+
const el = innerRef.current;
|
|
12
|
+
if (!el || !onKitbashChange) return;
|
|
13
|
+
|
|
14
|
+
const handleCustomChange = (e) => onKitbashChange(e);
|
|
15
|
+
el.addEventListener('kitbash-change', handleCustomChange);
|
|
16
|
+
return () => el.removeEventListener('kitbash-change', handleCustomChange);
|
|
17
|
+
}, [onKitbashChange]);
|
|
18
|
+
|
|
19
|
+
// Callback ref: assign + clear on unmount / ref change (object + function refs).
|
|
20
|
+
const setRefs = React.useCallback((node) => {
|
|
21
|
+
innerRef.current = node;
|
|
22
|
+
if (typeof ref === 'function') {
|
|
23
|
+
ref(node);
|
|
24
|
+
} else if (ref && typeof ref === 'object') {
|
|
25
|
+
ref.current = node;
|
|
26
|
+
}
|
|
27
|
+
}, [ref]);
|
|
28
|
+
|
|
29
|
+
return React.createElement('kitbash-theme-toggle', { ref: setRefs, ...props }, children);
|
|
30
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
|
|
4
|
+
export interface KitbashToggleGroupProps extends React.HTMLAttributes<HTMLElement> {
|
|
5
|
+
|
|
6
|
+
onKitbashChange?: (event: CustomEvent<{ props: Record<string, unknown>; state: Record<string, unknown> }>) => void;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
declare global {
|
|
10
|
+
namespace JSX {
|
|
11
|
+
interface IntrinsicElements {
|
|
12
|
+
'kitbash-toggle-group': KitbashToggleGroupProps & React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export declare const KitbashToggleGroup: React.ForwardRefExoticComponent<KitbashToggleGroupProps & React.RefAttributes<HTMLElement>>;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import '../vanilla/toggle-group.js';
|
|
4
|
+
|
|
5
|
+
export const KitbashToggleGroup = React.forwardRef(({ children, onKitbashChange, ...props }, ref) => {
|
|
6
|
+
const innerRef = React.useRef(null);
|
|
7
|
+
|
|
8
|
+
// kitbash-change is a CustomEvent — bridge manually. Native events (onClick, etc.)
|
|
9
|
+
// stay on ...props so React 19 binds them once (no double-fire).
|
|
10
|
+
React.useEffect(() => {
|
|
11
|
+
const el = innerRef.current;
|
|
12
|
+
if (!el || !onKitbashChange) return;
|
|
13
|
+
|
|
14
|
+
const handleCustomChange = (e) => onKitbashChange(e);
|
|
15
|
+
el.addEventListener('kitbash-change', handleCustomChange);
|
|
16
|
+
return () => el.removeEventListener('kitbash-change', handleCustomChange);
|
|
17
|
+
}, [onKitbashChange]);
|
|
18
|
+
|
|
19
|
+
// Callback ref: assign + clear on unmount / ref change (object + function refs).
|
|
20
|
+
const setRefs = React.useCallback((node) => {
|
|
21
|
+
innerRef.current = node;
|
|
22
|
+
if (typeof ref === 'function') {
|
|
23
|
+
ref(node);
|
|
24
|
+
} else if (ref && typeof ref === 'object') {
|
|
25
|
+
ref.current = node;
|
|
26
|
+
}
|
|
27
|
+
}, [ref]);
|
|
28
|
+
|
|
29
|
+
return React.createElement('kitbash-toggle-group', { ref: setRefs, ...props }, children);
|
|
30
|
+
});
|
package/dist/themes/dark.css
CHANGED
package/dist/themes/light.css
CHANGED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GENERATED FILE — do not edit by hand.
|
|
3
|
+
* Source: src/tokens/semantic.ts (+ presets)
|
|
4
|
+
* Regenerate: bun run tokens:build
|
|
5
|
+
*/
|
|
6
|
+
:root[data-kb-preset="terminal"][data-theme="dark"] {
|
|
7
|
+
--kb-color-bg-canvas: #050a05;
|
|
8
|
+
--kb-color-bg-surface: #0a120a;
|
|
9
|
+
--kb-color-bg-subtle: #0f1a0f;
|
|
10
|
+
--kb-color-bg-inverse: #d1fae5;
|
|
11
|
+
--kb-color-fg-default: #4ade80;
|
|
12
|
+
--kb-color-fg-muted: #a3f2b0;
|
|
13
|
+
--kb-color-fg-subtle: #00cc33;
|
|
14
|
+
--kb-color-fg-on-accent: #050a05;
|
|
15
|
+
--kb-color-fg-on-inverse: #050a05;
|
|
16
|
+
--kb-color-border-default: #00e637;
|
|
17
|
+
--kb-color-border-muted: #00b42d;
|
|
18
|
+
--kb-color-border-focus: #00ff41;
|
|
19
|
+
--kb-color-accent-default: #00ff41;
|
|
20
|
+
--kb-color-accent-hover: #00e637;
|
|
21
|
+
--kb-color-accent-subtle: rgba(74, 222, 128, 0.1);
|
|
22
|
+
--kb-color-danger-default: #f85149;
|
|
23
|
+
--kb-color-danger-subtle: #2d1214;
|
|
24
|
+
--kb-color-success-default: #4ade80;
|
|
25
|
+
--kb-color-success-subtle: #12261e;
|
|
26
|
+
--kb-color-warning-default: #d29922;
|
|
27
|
+
--kb-color-warning-subtle: #2a2111;
|
|
28
|
+
--kb-space-2xs: 2px;
|
|
29
|
+
--kb-space-xs: 4px;
|
|
30
|
+
--kb-space-sm: 8px;
|
|
31
|
+
--kb-space-md: 16px;
|
|
32
|
+
--kb-space-lg: 24px;
|
|
33
|
+
--kb-space-xl: 32px;
|
|
34
|
+
--kb-space-2xl: 48px;
|
|
35
|
+
--kb-radius-sm: 2px;
|
|
36
|
+
--kb-radius-md: 4px;
|
|
37
|
+
--kb-radius-lg: 6px;
|
|
38
|
+
--kb-radius-full: 9999px;
|
|
39
|
+
--kb-font-family-sans: 'VT323', ui-monospace, 'Courier New', monospace;
|
|
40
|
+
--kb-font-size-sm: 0.875rem;
|
|
41
|
+
--kb-font-size-md: 1rem;
|
|
42
|
+
--kb-font-size-lg: 1.125rem;
|
|
43
|
+
--kb-font-size-xl: 1.25rem;
|
|
44
|
+
--kb-font-weight-regular: 400;
|
|
45
|
+
--kb-font-weight-medium: 500;
|
|
46
|
+
--kb-font-weight-semibold: 600;
|
|
47
|
+
--kb-line-height-tight: 1.25;
|
|
48
|
+
--kb-line-height-normal: 1.625;
|
|
49
|
+
--kb-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.5);
|
|
50
|
+
--kb-shadow-md: 0 4px 16px rgba(0, 0, 0, 0.55);
|
|
51
|
+
--kb-focus-ring: 0 0 0 3px rgba(0, 255, 65, 0.35);
|
|
52
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GENERATED FILE — do not edit by hand.
|
|
3
|
+
* Source: src/tokens/semantic.ts (+ presets)
|
|
4
|
+
* Regenerate: bun run tokens:build
|
|
5
|
+
*/
|
|
6
|
+
:root[data-kb-preset="terminal"],
|
|
7
|
+
:root[data-kb-preset="terminal"][data-theme="light"] {
|
|
8
|
+
--kb-color-bg-canvas: #f8f9fa;
|
|
9
|
+
--kb-color-bg-surface: #ffffff;
|
|
10
|
+
--kb-color-bg-subtle: #eef2ee;
|
|
11
|
+
--kb-color-bg-inverse: #212529;
|
|
12
|
+
--kb-color-fg-default: #212529;
|
|
13
|
+
--kb-color-fg-muted: #495057;
|
|
14
|
+
--kb-color-fg-subtle: #6c757d;
|
|
15
|
+
--kb-color-fg-on-accent: #ffffff;
|
|
16
|
+
--kb-color-fg-on-inverse: #f8f9fa;
|
|
17
|
+
--kb-color-border-default: rgba(0, 102, 0, 0.25);
|
|
18
|
+
--kb-color-border-muted: rgba(0, 102, 0, 0.15);
|
|
19
|
+
--kb-color-border-focus: #006600;
|
|
20
|
+
--kb-color-accent-default: #006600;
|
|
21
|
+
--kb-color-accent-hover: #008000;
|
|
22
|
+
--kb-color-accent-subtle: rgba(0, 102, 0, 0.08);
|
|
23
|
+
--kb-color-danger-default: #b42318;
|
|
24
|
+
--kb-color-danger-subtle: #fee4e2;
|
|
25
|
+
--kb-color-success-default: #006600;
|
|
26
|
+
--kb-color-success-subtle: rgba(0, 102, 0, 0.08);
|
|
27
|
+
--kb-color-warning-default: #9a6700;
|
|
28
|
+
--kb-color-warning-subtle: #fff8c5;
|
|
29
|
+
--kb-space-2xs: 2px;
|
|
30
|
+
--kb-space-xs: 4px;
|
|
31
|
+
--kb-space-sm: 8px;
|
|
32
|
+
--kb-space-md: 16px;
|
|
33
|
+
--kb-space-lg: 24px;
|
|
34
|
+
--kb-space-xl: 32px;
|
|
35
|
+
--kb-space-2xl: 48px;
|
|
36
|
+
--kb-radius-sm: 2px;
|
|
37
|
+
--kb-radius-md: 4px;
|
|
38
|
+
--kb-radius-lg: 6px;
|
|
39
|
+
--kb-radius-full: 9999px;
|
|
40
|
+
--kb-font-family-sans: 'VT323', ui-monospace, 'Courier New', monospace;
|
|
41
|
+
--kb-font-size-sm: 0.875rem;
|
|
42
|
+
--kb-font-size-md: 1rem;
|
|
43
|
+
--kb-font-size-lg: 1.125rem;
|
|
44
|
+
--kb-font-size-xl: 1.25rem;
|
|
45
|
+
--kb-font-weight-regular: 400;
|
|
46
|
+
--kb-font-weight-medium: 500;
|
|
47
|
+
--kb-font-weight-semibold: 600;
|
|
48
|
+
--kb-line-height-tight: 1.25;
|
|
49
|
+
--kb-line-height-normal: 1.625;
|
|
50
|
+
--kb-shadow-sm: 0 1px 2px rgba(0, 102, 0, 0.08);
|
|
51
|
+
--kb-shadow-md: 0 4px 12px rgba(0, 102, 0, 0.1);
|
|
52
|
+
--kb-focus-ring: 0 0 0 3px rgba(0, 102, 0, 0.35);
|
|
53
|
+
}
|
package/dist/tokens/index.d.ts
CHANGED
|
@@ -3,5 +3,9 @@
|
|
|
3
3
|
* Import theme CSS in the app (or Storybook) so variables resolve:
|
|
4
4
|
* import '@ktbsh/ui/themes/light.css'
|
|
5
5
|
* import '@ktbsh/ui/themes/dark.css'
|
|
6
|
+
* import '@ktbsh/ui/themes/terminal/light.css' // optional preset
|
|
7
|
+
* import '@ktbsh/ui/themes/terminal/dark.css'
|
|
8
|
+
*
|
|
9
|
+
* Axes: applyTheme('light'|'dark') + applyPreset('default'|'terminal')
|
|
6
10
|
*/
|
|
7
|
-
export { applyTheme, cssVar, cssVarName, getTheme, type KitbashTheme, type SemanticTokenName, semanticTokens, type TokenValue, } from './semantic.ts';
|
|
11
|
+
export { applyPreset, applyTheme, cssVar, cssVarName, getPreset, getTheme, type KitbashPreset, type KitbashTheme, type SemanticTokenName, semanticTokens, type TokenValue, } from './semantic.ts';
|
package/dist/tokens/index.js
CHANGED
|
@@ -3,5 +3,9 @@
|
|
|
3
3
|
* Import theme CSS in the app (or Storybook) so variables resolve:
|
|
4
4
|
* import '@ktbsh/ui/themes/light.css'
|
|
5
5
|
* import '@ktbsh/ui/themes/dark.css'
|
|
6
|
+
* import '@ktbsh/ui/themes/terminal/light.css' // optional preset
|
|
7
|
+
* import '@ktbsh/ui/themes/terminal/dark.css'
|
|
8
|
+
*
|
|
9
|
+
* Axes: applyTheme('light'|'dark') + applyPreset('default'|'terminal')
|
|
6
10
|
*/
|
|
7
|
-
export { applyTheme, cssVar, cssVarName, getTheme, semanticTokens, } from "./semantic.js";
|
|
11
|
+
export { applyPreset, applyTheme, cssVar, cssVarName, getPreset, getTheme, semanticTokens, } from "./semantic.js";
|
|
@@ -1,10 +1,23 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Design tokens — single source of truth for names and light/dark values.
|
|
3
|
-
* CSS themes + kitbash `tokens.json` are generated from this module.
|
|
2
|
+
* Design tokens — single source of truth for names and **default** light/dark values.
|
|
3
|
+
* CSS themes + kitbash `tokens.json` are generated from this module + presets.
|
|
4
4
|
*
|
|
5
5
|
* CSS custom property for key `color-bg-canvas` → `--kb-color-bg-canvas`
|
|
6
|
+
*
|
|
7
|
+
* **Presets** (UI chrome / brand pack), orthogonal to light/dark:
|
|
8
|
+
* - `default` — neutral/blue DS (no `data-kb-preset` or `data-kb-preset="default"`)
|
|
9
|
+
* - `terminal` — Matrix-style pack from consumer blog (`data-kb-preset="terminal"`)
|
|
10
|
+
*
|
|
11
|
+
* See `docs/consumer-astro-blog-md.md`.
|
|
6
12
|
*/
|
|
13
|
+
/** Color scheme axis (night = dark). */
|
|
7
14
|
export type KitbashTheme = 'light' | 'dark';
|
|
15
|
+
/**
|
|
16
|
+
* Brand / UI-mode axis. Maps to blog `data-ui-mode`:
|
|
17
|
+
* - default ≈ regular
|
|
18
|
+
* - terminal ≈ terminal
|
|
19
|
+
*/
|
|
20
|
+
export type KitbashPreset = 'default' | 'terminal';
|
|
8
21
|
export type TokenValue = {
|
|
9
22
|
readonly light: string;
|
|
10
23
|
readonly dark: string;
|
|
@@ -201,9 +214,16 @@ export declare function cssVarName(token: SemanticTokenName): `--kb-${SemanticTo
|
|
|
201
214
|
/** `var(--kb-…)` reference for use in component styles. */
|
|
202
215
|
export declare function cssVar(token: SemanticTokenName): string;
|
|
203
216
|
/**
|
|
204
|
-
* Apply
|
|
217
|
+
* Apply color scheme on an element (default: document root in browsers).
|
|
205
218
|
* No-op without a DOM root (SSR) unless `root` is passed explicitly.
|
|
206
219
|
*/
|
|
207
220
|
export declare function applyTheme(theme: KitbashTheme, root?: HTMLElement): void;
|
|
208
221
|
/** Defaults to `light` when no DOM / no data-theme (SSR-safe). */
|
|
209
222
|
export declare function getTheme(root?: HTMLElement): KitbashTheme;
|
|
223
|
+
/**
|
|
224
|
+
* Apply brand preset (`data-kb-preset`). Omit/`default` uses base theme CSS only.
|
|
225
|
+
* Load matching CSS: `@ktbsh/ui/themes/terminal/light.css` + `dark.css` for terminal.
|
|
226
|
+
*/
|
|
227
|
+
export declare function applyPreset(preset: KitbashPreset, root?: HTMLElement): void;
|
|
228
|
+
/** Defaults to `default` when unset (SSR-safe). */
|
|
229
|
+
export declare function getPreset(root?: HTMLElement): KitbashPreset;
|