@dreamlake/dockit 0.2.21 → 0.2.23
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/THIRD_PARTY_NOTICES +26 -0
- package/dist/components/CodeBlock.js +3 -3
- package/dist/components/CodeTabs.js +7 -7
- package/dist/styles.css +22 -16
- package/dist/vendor/@dreamlake/uikit/src/components/Tabs/Tabs.js +334 -0
- package/dist/vendor/@dreamlake/uikit/src/lib/utils.js +56 -0
- package/package.json +7 -4
package/THIRD_PARTY_NOTICES
CHANGED
|
@@ -43,3 +43,29 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
43
43
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
44
44
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
45
45
|
SOFTWARE.
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
UIKit tab primitives: https://github.com/dreamlake-ai/uikit-workspace
|
|
50
|
+
|
|
51
|
+
MIT License
|
|
52
|
+
|
|
53
|
+
Copyright (c) 2026 DreamLake
|
|
54
|
+
|
|
55
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
56
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
57
|
+
in the Software without restriction, including without limitation the rights
|
|
58
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
59
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
60
|
+
furnished to do so, subject to the following conditions:
|
|
61
|
+
|
|
62
|
+
The above copyright notice and this permission notice shall be included in all
|
|
63
|
+
copies or substantial portions of the Software.
|
|
64
|
+
|
|
65
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
66
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
67
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
68
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
69
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
70
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
71
|
+
SOFTWARE.
|
|
@@ -99,7 +99,7 @@ function CodeBlock({ children, filename, lang }) {
|
|
|
99
99
|
"div",
|
|
100
100
|
{
|
|
101
101
|
className: "absolute top-0 right-0 z-10 flex items-center opacity-0 group-hover:opacity-100 focus-within:opacity-100 transition-opacity duration-150",
|
|
102
|
-
style: { gap: 6, padding: "8px 8px", isolation: "isolate" },
|
|
102
|
+
style: { gap: 6, padding: embedded ? "3px 8px" : "8px 8px", isolation: "isolate" },
|
|
103
103
|
children: [
|
|
104
104
|
/* @__PURE__ */ jsx(
|
|
105
105
|
"span",
|
|
@@ -111,8 +111,8 @@ function CodeBlock({ children, filename, lang }) {
|
|
|
111
111
|
zIndex: -1,
|
|
112
112
|
pointerEvents: "none",
|
|
113
113
|
borderRadius: 6,
|
|
114
|
-
background: "color-mix(in srgb, var(--color-doc-template-code) 88%, transparent)",
|
|
115
|
-
boxShadow: "0 0 10px 6px var(--color-doc-template-code)",
|
|
114
|
+
background: embedded ? "var(--color-doc-template-bg)" : "color-mix(in srgb, var(--color-doc-template-code) 88%, transparent)",
|
|
115
|
+
boxShadow: embedded ? void 0 : "0 0 10px 6px var(--color-doc-template-code)",
|
|
116
116
|
backdropFilter: "blur(8px)",
|
|
117
117
|
WebkitBackdropFilter: "blur(8px)"
|
|
118
118
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { jsx, Fragment, jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { Children, isValidElement, useState, useId, useRef } from "react";
|
|
3
|
+
import { Tabs, TabsList, TabsTrigger } from "../vendor/@dreamlake/uikit/src/components/Tabs/Tabs.js";
|
|
3
4
|
import { CodeTabsContext } from "./code-tabs-context.js";
|
|
4
5
|
function CodeExample({ children }) {
|
|
5
6
|
return /* @__PURE__ */ jsx(Fragment, { children });
|
|
@@ -11,12 +12,12 @@ function CodeTabs({ children, "aria-label": label = "Code examples" }) {
|
|
|
11
12
|
const id = useId();
|
|
12
13
|
const buttons = useRef([]);
|
|
13
14
|
if (!examples.length) return null;
|
|
14
|
-
return /* @__PURE__ */
|
|
15
|
-
/* @__PURE__ */ jsx("div", { className: "dockit-code-tabs-header", children: /* @__PURE__ */ jsx(
|
|
16
|
-
|
|
15
|
+
return /* @__PURE__ */ jsx("div", { "data-code-tabs": true, className: "dockit-code-tabs group relative", children: /* @__PURE__ */ jsxs(Tabs, { value: String(active), onValueChange: (value) => setSelected(Number(value)), children: [
|
|
16
|
+
/* @__PURE__ */ jsx("div", { className: "dockit-code-tabs-header", children: /* @__PURE__ */ jsx(TabsList, { "aria-label": label, className: "dockit-code-tabs-list border-0 font-doc-template-ui", children: examples.map((example, index) => /* @__PURE__ */ jsx(
|
|
17
|
+
TabsTrigger,
|
|
17
18
|
{
|
|
18
|
-
|
|
19
|
-
|
|
19
|
+
value: String(index),
|
|
20
|
+
className: "shrink-0 font-doc-template-mono font-medium data-[active]:font-semibold text-doc-template-muted hover:text-doc-template-ink data-[active]:text-doc-template-ink text-[12px]",
|
|
20
21
|
ref: (element) => {
|
|
21
22
|
buttons.current[index] = element;
|
|
22
23
|
},
|
|
@@ -24,7 +25,6 @@ function CodeTabs({ children, "aria-label": label = "Code examples" }) {
|
|
|
24
25
|
"aria-controls": `${id}-panel-${index}`,
|
|
25
26
|
"aria-selected": active === index,
|
|
26
27
|
tabIndex: active === index ? 0 : -1,
|
|
27
|
-
onClick: () => setSelected(index),
|
|
28
28
|
onKeyDown: (event) => {
|
|
29
29
|
let next;
|
|
30
30
|
if (event.key === "ArrowRight") next = (index + 1) % examples.length;
|
|
@@ -52,7 +52,7 @@ function CodeTabs({ children, "aria-label": label = "Code examples" }) {
|
|
|
52
52
|
},
|
|
53
53
|
example.key ?? index
|
|
54
54
|
)) })
|
|
55
|
-
] });
|
|
55
|
+
] }) });
|
|
56
56
|
}
|
|
57
57
|
export {
|
|
58
58
|
CodeExample,
|
package/dist/styles.css
CHANGED
|
@@ -387,30 +387,36 @@
|
|
|
387
387
|
overflow: hidden;
|
|
388
388
|
}
|
|
389
389
|
.dockit-code-tabs-header {
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
min-height:
|
|
393
|
-
padding
|
|
394
|
-
}
|
|
395
|
-
.dockit-code-tabs-list {
|
|
390
|
+
background: var(--color-doc-template-bg);
|
|
391
|
+
box-shadow: inset 0 -1px var(--color-doc-template-faint);
|
|
392
|
+
min-height: 30px;
|
|
393
|
+
padding: 0 156px 0 12px;
|
|
394
|
+
}
|
|
395
|
+
.dockit-code-tabs-list { overflow-x: auto; min-height: 30px; gap: 2px; }
|
|
396
|
+
/* Raised file-tab geometry follows Studio's chat TabStrip. UIKit supplies the
|
|
397
|
+
compound primitives; the active page-colored bottom edge opens the baseline. */
|
|
396
398
|
.dockit-code-tabs-list [role='tab'] {
|
|
397
|
-
|
|
398
|
-
padding:
|
|
399
|
-
border:
|
|
400
|
-
border-
|
|
399
|
+
margin: 0 1px;
|
|
400
|
+
padding: 3px 9px 4px;
|
|
401
|
+
border: 1px solid transparent;
|
|
402
|
+
border-radius: 6px 6px 0 0;
|
|
401
403
|
background: transparent;
|
|
402
|
-
|
|
403
|
-
font: inherit;
|
|
404
|
-
font-size: 12px;
|
|
405
|
-
cursor: pointer;
|
|
404
|
+
line-height: 18px;
|
|
406
405
|
}
|
|
407
406
|
.dockit-code-tabs-list [role='tab'][aria-selected='true'] {
|
|
408
|
-
color: var(--color-doc-template-
|
|
409
|
-
border-bottom-color: var(--color-doc-template-
|
|
407
|
+
border-color: var(--color-doc-template-faint);
|
|
408
|
+
border-bottom-color: var(--color-doc-template-bg);
|
|
409
|
+
background: var(--color-doc-template-bg);
|
|
410
410
|
}
|
|
411
411
|
.dockit-code-tabs-list [role='tab']:focus-visible,
|
|
412
412
|
.dockit-code-tabs [role='tabpanel']:focus-visible {
|
|
413
413
|
outline: 2px solid var(--color-doc-template-accent);
|
|
414
414
|
outline-offset: -3px;
|
|
415
415
|
}
|
|
416
|
+
.dockit-code-tabs [role='tabpanel'] {
|
|
417
|
+
border: 1px solid var(--color-doc-template-faint);
|
|
418
|
+
border-top: 0;
|
|
419
|
+
border-radius: 0 0 var(--radius-doc-template) var(--radius-doc-template);
|
|
420
|
+
background: var(--color-doc-template-code);
|
|
421
|
+
}
|
|
416
422
|
.dockit-code-tabs [role='tabpanel'][hidden] { display: none; }
|
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState, useRef, useEffect, useContext, createContext } from "react";
|
|
3
|
+
import { cn } from "../../lib/utils.js";
|
|
4
|
+
const TabsContext = createContext(null);
|
|
5
|
+
function useTabsContext(name) {
|
|
6
|
+
const c = useContext(TabsContext);
|
|
7
|
+
if (!c) throw new Error(`<${name}> must be used inside <Tabs>`);
|
|
8
|
+
return c;
|
|
9
|
+
}
|
|
10
|
+
const underlineSizeMap = {
|
|
11
|
+
xs: "text-uikit-11 h-5 pt-px pb-[5px] mr-3",
|
|
12
|
+
sm: "text-uikit-12 h-[27px] pt-1 pb-2 mr-[18px]",
|
|
13
|
+
md: "text-[13.5px] h-[22px] pt-px pb-2 mr-[18px]",
|
|
14
|
+
lg: "text-[15px] h-[34px] pt-1 pb-3 mr-[22px]"
|
|
15
|
+
};
|
|
16
|
+
const segmentConfig = {
|
|
17
|
+
xs: {
|
|
18
|
+
inset: 1,
|
|
19
|
+
containerR: 3,
|
|
20
|
+
pillR: 3,
|
|
21
|
+
buttonR: 3,
|
|
22
|
+
padV: 1,
|
|
23
|
+
padH: 4,
|
|
24
|
+
iconSize: 9
|
|
25
|
+
},
|
|
26
|
+
sm: {
|
|
27
|
+
inset: 1,
|
|
28
|
+
containerR: 4,
|
|
29
|
+
pillR: 4,
|
|
30
|
+
buttonR: 4,
|
|
31
|
+
padV: 2,
|
|
32
|
+
padH: 5,
|
|
33
|
+
iconSize: 10
|
|
34
|
+
},
|
|
35
|
+
md: {
|
|
36
|
+
inset: 2,
|
|
37
|
+
containerR: 6,
|
|
38
|
+
pillR: 5,
|
|
39
|
+
buttonR: 5,
|
|
40
|
+
padV: 4,
|
|
41
|
+
padH: 6,
|
|
42
|
+
iconSize: 12
|
|
43
|
+
},
|
|
44
|
+
lg: {
|
|
45
|
+
inset: 3,
|
|
46
|
+
containerR: 8,
|
|
47
|
+
pillR: 6,
|
|
48
|
+
buttonR: 6,
|
|
49
|
+
padV: 5,
|
|
50
|
+
padH: 7,
|
|
51
|
+
iconSize: 14
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
function UnderlineTabItem({
|
|
55
|
+
tab,
|
|
56
|
+
active,
|
|
57
|
+
size,
|
|
58
|
+
innerRef,
|
|
59
|
+
onClick
|
|
60
|
+
}) {
|
|
61
|
+
const isSmall = size === "xs" || size === "sm";
|
|
62
|
+
return /* @__PURE__ */ jsxs(
|
|
63
|
+
"div",
|
|
64
|
+
{
|
|
65
|
+
ref: innerRef,
|
|
66
|
+
role: "tab",
|
|
67
|
+
"aria-selected": active,
|
|
68
|
+
"data-active": active || void 0,
|
|
69
|
+
"data-small": isSmall || void 0,
|
|
70
|
+
onClick,
|
|
71
|
+
className: cn(
|
|
72
|
+
"group/tab relative inline-flex items-center gap-1.5 cursor-pointer select-none whitespace-nowrap",
|
|
73
|
+
"font-uikit-ui tracking-uikit-snug",
|
|
74
|
+
"transition-[color,opacity] duration-[120ms]",
|
|
75
|
+
underlineSizeMap[size],
|
|
76
|
+
// Color: muted by default, ink when active.
|
|
77
|
+
"text-uikit-muted data-[active]:text-uikit-ink",
|
|
78
|
+
// Weight (only when !isSmall).
|
|
79
|
+
"[&:not([data-small])]:font-medium",
|
|
80
|
+
"[&:not([data-small])]:data-[active]:font-semibold",
|
|
81
|
+
// Opacity (large variants): rest 0.45, hover 0.7, active 1.
|
|
82
|
+
"[&:not([data-small])]:opacity-45",
|
|
83
|
+
"[&:not([data-small])]:hover:opacity-70",
|
|
84
|
+
"[&:not([data-small])]:data-[active]:opacity-100",
|
|
85
|
+
// Opacity (small variants): rest 0.75, hover/active 1.
|
|
86
|
+
"data-[small]:opacity-75",
|
|
87
|
+
"data-[small]:hover:opacity-100",
|
|
88
|
+
"data-[small]:data-[active]:opacity-100"
|
|
89
|
+
),
|
|
90
|
+
children: [
|
|
91
|
+
/* @__PURE__ */ jsx("span", { children: tab.label }),
|
|
92
|
+
tab.count != null && /* @__PURE__ */ jsx(
|
|
93
|
+
"span",
|
|
94
|
+
{
|
|
95
|
+
className: cn(
|
|
96
|
+
"font-uikit-mono text-[9.5px] rounded-full px-1.5 py-px tracking-uikit-wide",
|
|
97
|
+
"transition-[background-color,opacity] duration-[120ms]",
|
|
98
|
+
// Weight + opacity track the parent's active/hover state.
|
|
99
|
+
"font-medium opacity-55 group-hover/tab:opacity-90 group-data-[active]/tab:opacity-100",
|
|
100
|
+
"group-data-[active]/tab:font-semibold",
|
|
101
|
+
// Background tracks parent state — uses currentColor for theme inheritance.
|
|
102
|
+
"bg-[color-mix(in_oklab,currentColor_5%,transparent)]",
|
|
103
|
+
"group-data-[active]/tab:bg-[color-mix(in_oklab,currentColor_12%,transparent)]"
|
|
104
|
+
),
|
|
105
|
+
children: tab.count
|
|
106
|
+
}
|
|
107
|
+
)
|
|
108
|
+
]
|
|
109
|
+
}
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
function Tabs(props) {
|
|
113
|
+
if (props.children !== void 0) {
|
|
114
|
+
return /* @__PURE__ */ jsx(
|
|
115
|
+
TabsRoot,
|
|
116
|
+
{
|
|
117
|
+
value: props.value,
|
|
118
|
+
defaultValue: props.defaultValue,
|
|
119
|
+
onValueChange: props.onValueChange ?? props.onChange,
|
|
120
|
+
className: props.className,
|
|
121
|
+
children: props.children
|
|
122
|
+
}
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
return /* @__PURE__ */ jsx(TabsData, { ...props });
|
|
126
|
+
}
|
|
127
|
+
function TabsData({
|
|
128
|
+
tabs,
|
|
129
|
+
defaultValue,
|
|
130
|
+
value,
|
|
131
|
+
onChange,
|
|
132
|
+
onValueChange,
|
|
133
|
+
variant = "underline",
|
|
134
|
+
size = "md",
|
|
135
|
+
indicatorHeight,
|
|
136
|
+
className
|
|
137
|
+
}) {
|
|
138
|
+
const [internalValue, setInternalValue] = useState(
|
|
139
|
+
defaultValue ?? tabs?.[0]?.value ?? ""
|
|
140
|
+
);
|
|
141
|
+
const [bar, setBar] = useState({
|
|
142
|
+
left: 0,
|
|
143
|
+
width: 0,
|
|
144
|
+
height: 0,
|
|
145
|
+
ready: false
|
|
146
|
+
});
|
|
147
|
+
const tabRefs = useRef({});
|
|
148
|
+
const activeValue = value !== void 0 ? value : internalValue;
|
|
149
|
+
const handleTabClick = (newValue) => {
|
|
150
|
+
if (value === void 0) setInternalValue(newValue);
|
|
151
|
+
(onValueChange ?? onChange)?.(newValue);
|
|
152
|
+
};
|
|
153
|
+
useEffect(() => {
|
|
154
|
+
if (value !== void 0) setInternalValue(value);
|
|
155
|
+
}, [value]);
|
|
156
|
+
useEffect(() => {
|
|
157
|
+
const el = tabRefs.current[activeValue];
|
|
158
|
+
if (!el) return;
|
|
159
|
+
setBar({
|
|
160
|
+
left: el.offsetLeft,
|
|
161
|
+
width: el.offsetWidth,
|
|
162
|
+
height: el.offsetHeight,
|
|
163
|
+
ready: true
|
|
164
|
+
});
|
|
165
|
+
}, [activeValue, tabs?.length]);
|
|
166
|
+
const segCfg = segmentConfig[size];
|
|
167
|
+
const tabList = tabs ?? [];
|
|
168
|
+
return /* @__PURE__ */ jsxs(
|
|
169
|
+
"div",
|
|
170
|
+
{
|
|
171
|
+
role: "tablist",
|
|
172
|
+
className: cn(
|
|
173
|
+
"relative font-uikit-ui",
|
|
174
|
+
variant === "underline" && "flex items-end",
|
|
175
|
+
variant === "segment" && "inline-flex bg-uikit-ink-5",
|
|
176
|
+
className
|
|
177
|
+
),
|
|
178
|
+
style: variant === "segment" ? {
|
|
179
|
+
padding: segCfg.inset,
|
|
180
|
+
gap: 1,
|
|
181
|
+
borderRadius: segCfg.containerR
|
|
182
|
+
} : void 0,
|
|
183
|
+
children: [
|
|
184
|
+
variant === "underline" && /* @__PURE__ */ jsx(
|
|
185
|
+
"span",
|
|
186
|
+
{
|
|
187
|
+
className: "absolute pointer-events-none z-[2] bg-uikit-ink",
|
|
188
|
+
style: {
|
|
189
|
+
left: bar.left,
|
|
190
|
+
width: bar.width,
|
|
191
|
+
height: indicatorHeight ?? 4,
|
|
192
|
+
bottom: -1,
|
|
193
|
+
transition: bar.ready ? "left 280ms cubic-bezier(.4,0,.2,1), width 280ms cubic-bezier(.4,0,.2,1)" : "none"
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
),
|
|
197
|
+
variant === "segment" && /* @__PURE__ */ jsx(
|
|
198
|
+
"div",
|
|
199
|
+
{
|
|
200
|
+
"aria-hidden": true,
|
|
201
|
+
className: "absolute pointer-events-none bg-uikit-bg shadow-[0_1px_2px_var(--shadow-tint-1)]",
|
|
202
|
+
style: {
|
|
203
|
+
top: segCfg.inset,
|
|
204
|
+
bottom: segCfg.inset,
|
|
205
|
+
left: 0,
|
|
206
|
+
width: bar.width,
|
|
207
|
+
transform: `translateX(${bar.left}px)`,
|
|
208
|
+
borderRadius: segCfg.pillR,
|
|
209
|
+
opacity: bar.ready ? 1 : 0,
|
|
210
|
+
// Position springs (--uikit-ease-thumb, the theme toggle's curve);
|
|
211
|
+
// width does NOT. An overshoot is a thumb arriving with weight when
|
|
212
|
+
// it only slides, but a width that overshoots is the pill's far
|
|
213
|
+
// edge lunging past the label it is meant to sit under — two
|
|
214
|
+
// segments of different widths made that obvious. So width rides
|
|
215
|
+
// the same duration on a curve that only decelerates, and the two
|
|
216
|
+
// land together.
|
|
217
|
+
transition: bar.ready ? "transform var(--uikit-dur-thumb, 420ms) var(--uikit-ease-thumb, cubic-bezier(.34,1.45,.55,1)), width var(--uikit-dur-thumb, 420ms) cubic-bezier(.32,.72,0,1)" : "none"
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
),
|
|
221
|
+
tabList.map((tab) => {
|
|
222
|
+
const active = tab.value === activeValue;
|
|
223
|
+
if (variant === "underline") {
|
|
224
|
+
return /* @__PURE__ */ jsx(
|
|
225
|
+
UnderlineTabItem,
|
|
226
|
+
{
|
|
227
|
+
tab,
|
|
228
|
+
active,
|
|
229
|
+
size,
|
|
230
|
+
innerRef: (el) => {
|
|
231
|
+
tabRefs.current[tab.value] = el;
|
|
232
|
+
},
|
|
233
|
+
onClick: () => handleTabClick(tab.value)
|
|
234
|
+
},
|
|
235
|
+
tab.value
|
|
236
|
+
);
|
|
237
|
+
}
|
|
238
|
+
return /* @__PURE__ */ jsx(
|
|
239
|
+
"button",
|
|
240
|
+
{
|
|
241
|
+
ref: (el) => {
|
|
242
|
+
tabRefs.current[tab.value] = el;
|
|
243
|
+
},
|
|
244
|
+
type: "button",
|
|
245
|
+
title: tab.title,
|
|
246
|
+
"aria-pressed": active,
|
|
247
|
+
"data-active": active || void 0,
|
|
248
|
+
onClick: () => handleTabClick(tab.value),
|
|
249
|
+
className: cn(
|
|
250
|
+
"relative z-[1] inline-flex items-center justify-center cursor-pointer select-none",
|
|
251
|
+
"appearance-none border-0 bg-transparent outline-none",
|
|
252
|
+
"text-uikit-muted data-[active]:text-uikit-ink",
|
|
253
|
+
"transition-colors duration-[160ms]"
|
|
254
|
+
),
|
|
255
|
+
style: {
|
|
256
|
+
padding: `${segCfg.padV}px ${segCfg.padH}px`,
|
|
257
|
+
borderRadius: segCfg.buttonR,
|
|
258
|
+
fontSize: segCfg.iconSize,
|
|
259
|
+
lineHeight: 1
|
|
260
|
+
},
|
|
261
|
+
children: tab.label
|
|
262
|
+
},
|
|
263
|
+
tab.value
|
|
264
|
+
);
|
|
265
|
+
})
|
|
266
|
+
]
|
|
267
|
+
}
|
|
268
|
+
);
|
|
269
|
+
}
|
|
270
|
+
function TabsRoot({
|
|
271
|
+
value,
|
|
272
|
+
defaultValue,
|
|
273
|
+
onValueChange,
|
|
274
|
+
className,
|
|
275
|
+
children
|
|
276
|
+
}) {
|
|
277
|
+
const [internal, setInternal] = useState(defaultValue ?? "");
|
|
278
|
+
const isControlled = value !== void 0;
|
|
279
|
+
const current = isControlled ? value : internal;
|
|
280
|
+
const setValue = (v) => {
|
|
281
|
+
if (!isControlled) setInternal(v);
|
|
282
|
+
onValueChange?.(v);
|
|
283
|
+
};
|
|
284
|
+
return /* @__PURE__ */ jsx(TabsContext.Provider, { value: { value: current, setValue }, children: /* @__PURE__ */ jsx("div", { className: cn("flex flex-col", className), children }) });
|
|
285
|
+
}
|
|
286
|
+
function TabsList({ className, ...props }) {
|
|
287
|
+
return /* @__PURE__ */ jsx(
|
|
288
|
+
"div",
|
|
289
|
+
{
|
|
290
|
+
role: "tablist",
|
|
291
|
+
className: cn(
|
|
292
|
+
"flex items-end gap-3 border-b border-uikit-faint font-uikit-ui",
|
|
293
|
+
className
|
|
294
|
+
),
|
|
295
|
+
...props
|
|
296
|
+
}
|
|
297
|
+
);
|
|
298
|
+
}
|
|
299
|
+
function TabsTrigger({
|
|
300
|
+
value,
|
|
301
|
+
className,
|
|
302
|
+
children,
|
|
303
|
+
onClick,
|
|
304
|
+
...props
|
|
305
|
+
}) {
|
|
306
|
+
const ctx = useTabsContext("TabsTrigger");
|
|
307
|
+
const active = ctx.value === value;
|
|
308
|
+
return /* @__PURE__ */ jsx(
|
|
309
|
+
"button",
|
|
310
|
+
{
|
|
311
|
+
type: "button",
|
|
312
|
+
role: "tab",
|
|
313
|
+
"aria-selected": active,
|
|
314
|
+
"data-active": active || void 0,
|
|
315
|
+
onClick: (e) => {
|
|
316
|
+
onClick?.(e);
|
|
317
|
+
ctx.setValue(value);
|
|
318
|
+
},
|
|
319
|
+
className: cn(
|
|
320
|
+
"relative -mb-px cursor-pointer select-none whitespace-nowrap border-b-2 border-transparent",
|
|
321
|
+
"pb-1.5 pt-1 text-uikit-12 text-uikit-muted transition-colors",
|
|
322
|
+
"hover:text-uikit-ink data-[active]:border-uikit-ink data-[active]:text-uikit-ink data-[active]:font-medium",
|
|
323
|
+
className
|
|
324
|
+
),
|
|
325
|
+
...props,
|
|
326
|
+
children
|
|
327
|
+
}
|
|
328
|
+
);
|
|
329
|
+
}
|
|
330
|
+
export {
|
|
331
|
+
Tabs,
|
|
332
|
+
TabsList,
|
|
333
|
+
TabsTrigger
|
|
334
|
+
};
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { clsx } from "clsx";
|
|
2
|
+
import { extendTailwindMerge } from "tailwind-merge";
|
|
3
|
+
const twMerge = extendTailwindMerge({
|
|
4
|
+
override: {
|
|
5
|
+
// Standard `font-size` group (covers stock `text-base`, `text-[Npx]`, etc.)
|
|
6
|
+
// no longer invalidates `leading-*`. Required so e.g. `text-[13.5px]`
|
|
7
|
+
// and `leading-[1.2]` can coexist on Tag.
|
|
8
|
+
conflictingClassGroups: {
|
|
9
|
+
"font-size": []
|
|
10
|
+
}
|
|
11
|
+
},
|
|
12
|
+
extend: {
|
|
13
|
+
classGroups: {
|
|
14
|
+
// Custom group for our font-size scale. Only conflicts with itself.
|
|
15
|
+
"uikit-font-size": [
|
|
16
|
+
"text-uikit-9",
|
|
17
|
+
"text-uikit-10",
|
|
18
|
+
"text-uikit-11",
|
|
19
|
+
"text-uikit-12",
|
|
20
|
+
"text-uikit-13",
|
|
21
|
+
"text-uikit-14",
|
|
22
|
+
"text-uikit-17",
|
|
23
|
+
"text-uikit-22"
|
|
24
|
+
],
|
|
25
|
+
// Text color utilities — token aliases + alpha-mix presets.
|
|
26
|
+
"text-color": [
|
|
27
|
+
"text-uikit-ink",
|
|
28
|
+
"text-uikit-muted",
|
|
29
|
+
"text-uikit-bg",
|
|
30
|
+
"text-uikit-panel",
|
|
31
|
+
"text-uikit-rail",
|
|
32
|
+
"text-uikit-accent",
|
|
33
|
+
"text-uikit-accent-soft",
|
|
34
|
+
"text-uikit-faint",
|
|
35
|
+
"text-uikit-chip",
|
|
36
|
+
"text-uikit-search",
|
|
37
|
+
"text-uikit-selected",
|
|
38
|
+
"text-uikit-danger",
|
|
39
|
+
"text-uikit-ink-4",
|
|
40
|
+
"text-uikit-ink-5",
|
|
41
|
+
"text-uikit-ink-6",
|
|
42
|
+
"text-uikit-ink-8",
|
|
43
|
+
"text-uikit-ink-12",
|
|
44
|
+
"text-uikit-ink-50",
|
|
45
|
+
"text-uikit-accent-12",
|
|
46
|
+
"text-uikit-danger-8"
|
|
47
|
+
]
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
function cn(...inputs) {
|
|
52
|
+
return twMerge(clsx(inputs));
|
|
53
|
+
}
|
|
54
|
+
export {
|
|
55
|
+
cn
|
|
56
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dreamlake/dockit",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.23",
|
|
4
4
|
"description": "The DreamLake documentation shell — Vike + React + Tailwind v4 + MDX docs framework with sidebar, TOC, search, and theming",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -42,10 +42,10 @@
|
|
|
42
42
|
"@mdx-js/react": ">=3.0.0",
|
|
43
43
|
"react": ">=19.0.0",
|
|
44
44
|
"react-dom": ">=19.0.0",
|
|
45
|
+
"tailwindcss": "^4.0.0",
|
|
45
46
|
"vike": "^0.4.210",
|
|
46
47
|
"vike-react": "^0.5.0",
|
|
47
|
-
"vite": ">=6.0.0"
|
|
48
|
-
"tailwindcss": "^4.0.0"
|
|
48
|
+
"vite": ">=6.0.0"
|
|
49
49
|
},
|
|
50
50
|
"peerDependenciesMeta": {
|
|
51
51
|
"vite": {
|
|
@@ -57,11 +57,13 @@
|
|
|
57
57
|
"@shikijs/rehype": "^1.24.0",
|
|
58
58
|
"@tailwindcss/vite": "^4.0.0",
|
|
59
59
|
"@vitejs/plugin-react": "^4.3.4",
|
|
60
|
+
"clsx": "^2.1.1",
|
|
60
61
|
"rehype-slug": "^6.0.0",
|
|
61
62
|
"remark-frontmatter": "^5.0.0",
|
|
62
63
|
"remark-gfm": "^4.0.0",
|
|
63
64
|
"remark-mdx-frontmatter": "^5.2.0",
|
|
64
65
|
"shiki": "^1.24.0",
|
|
66
|
+
"tailwind-merge": "^3.7.0",
|
|
65
67
|
"yaml": "^2.9.0"
|
|
66
68
|
},
|
|
67
69
|
"devDependencies": {
|
|
@@ -71,12 +73,13 @@
|
|
|
71
73
|
"@types/react-dom": "latest",
|
|
72
74
|
"react": "latest",
|
|
73
75
|
"react-dom": "latest",
|
|
76
|
+
"tailwindcss": "^4.0.0",
|
|
74
77
|
"typescript": "^5.7.0",
|
|
75
78
|
"vike": "^0.4.210",
|
|
76
79
|
"vike-react": "^0.5.0",
|
|
77
80
|
"vite": "^7.0.0",
|
|
78
81
|
"vite-plugin-dts": "^4.3.0",
|
|
79
|
-
"
|
|
82
|
+
"@dreamlake/uikit": "0.1.15"
|
|
80
83
|
},
|
|
81
84
|
"scripts": {
|
|
82
85
|
"build": "vite build",
|