@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.
@@ -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__ */ jsxs("div", { "data-code-tabs": true, className: "dockit-code-tabs group relative border border-doc-template-faint bg-doc-template-code", children: [
15
- /* @__PURE__ */ jsx("div", { className: "dockit-code-tabs-header", children: /* @__PURE__ */ jsx("div", { role: "tablist", "aria-label": label, className: "dockit-code-tabs-list", children: examples.map((example, index) => /* @__PURE__ */ jsx(
16
- "button",
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
- type: "button",
19
- role: "tab",
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
- border-bottom: 1px solid var(--color-doc-template-faint);
391
- background: color-mix(in srgb, var(--color-doc-template-ink) 3%, transparent);
392
- min-height: 40px;
393
- padding-right: 156px;
394
- }
395
- .dockit-code-tabs-list { display: flex; overflow-x: auto; }
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
- flex-shrink: 0;
398
- padding: 10px 14px;
399
- border: 0;
400
- border-bottom: 2px solid transparent;
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
- color: var(--color-doc-template-muted);
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-ink);
409
- border-bottom-color: var(--color-doc-template-accent);
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.21",
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
- "tailwindcss": "^4.0.0"
82
+ "@dreamlake/uikit": "0.1.15"
80
83
  },
81
84
  "scripts": {
82
85
  "build": "vite build",