@loykin/designkit 0.0.1-dev.0 → 0.0.1-dev.2

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/index.js CHANGED
@@ -7,7 +7,7 @@ import { useRender } from '@base-ui/react/use-render';
7
7
  import { cva } from 'class-variance-authority';
8
8
  import { Button as Button$1 } from '@base-ui/react/button';
9
9
  import { Checkbox as Checkbox$1 } from '@base-ui/react/checkbox';
10
- import { KeyRound, Palette, Type, FileText, LayoutDashboard, Layers, Table2, ChevronDownIcon, CheckIcon, ArrowLeft, CheckCircle2, AlertCircle, Clock, XCircle, Plus, Search, Users, RefreshCw, ChevronUpIcon, Check, Download, ChevronRightIcon, XIcon, PanelLeftIcon } from 'lucide-react';
10
+ import { GripHorizontal, CheckIcon, ChevronRightIcon, ChevronDownIcon, ChevronUpIcon, XIcon, PanelLeftIcon, SlidersHorizontal, Check } from 'lucide-react';
11
11
  import { Menu } from '@base-ui/react/menu';
12
12
  import { Input as Input$1 } from '@base-ui/react/input';
13
13
  import { Popover as Popover$1 } from '@base-ui/react/popover';
@@ -17,12 +17,11 @@ import { Select as Select$1 } from '@base-ui/react/select';
17
17
  import { Separator as Separator$1 } from '@base-ui/react/separator';
18
18
  import { Dialog } from '@base-ui/react/dialog';
19
19
  import * as React2 from 'react';
20
- import React2__default, { useMemo, Children, useState, Fragment, createElement, useEffect } from 'react';
20
+ import React2__default, { forwardRef, useMemo, Children, useState, Fragment, useEffect } from 'react';
21
21
  import { Tooltip as Tooltip$1 } from '@base-ui/react/tooltip';
22
22
  import { Slider as Slider$1 } from '@base-ui/react/slider';
23
23
  import { Switch as Switch$1 } from '@base-ui/react/switch';
24
24
  import { Tabs as Tabs$1 } from '@base-ui/react/tabs';
25
- import { DataGrid, DataGridPaginationCompact, DataGridCard, GlobalSearch, DragHandleCell, DataGridInfinity, DataGridDrag } from '@loykin/gridkit';
26
25
  import { create } from 'zustand';
27
26
 
28
27
  // src/components/ui/avatar.tsx
@@ -1966,517 +1965,6 @@ function TabsContent({ className, ...props }) {
1966
1965
  }
1967
1966
  );
1968
1967
  }
1969
-
1970
- // src/components/templates/definitions.ts
1971
- var topBarOptions = [
1972
- {
1973
- key: "topBarShow",
1974
- label: "Top Bar",
1975
- type: "select",
1976
- choices: [
1977
- { value: "show", label: "Show" },
1978
- { value: "hide", label: "Hide" }
1979
- ],
1980
- defaultValue: "show"
1981
- },
1982
- {
1983
- key: "topBarVariant",
1984
- label: "Border",
1985
- type: "select",
1986
- choices: [
1987
- { value: "ghost", label: "None" },
1988
- { value: "default", label: "Line" }
1989
- ],
1990
- defaultValue: "ghost"
1991
- },
1992
- {
1993
- key: "topBarBg",
1994
- label: "Background",
1995
- type: "select",
1996
- choices: [
1997
- { value: "transparent", label: "Default" },
1998
- { value: "muted", label: "Muted" },
1999
- { value: "card", label: "Card" }
2000
- ],
2001
- defaultValue: "transparent"
2002
- }
2003
- ];
2004
- var loginOptions = [
2005
- {
2006
- key: "loginLayout",
2007
- label: "Layout",
2008
- type: "select",
2009
- choices: [
2010
- { value: "centered", label: "Centered" },
2011
- { value: "split", label: "Split" }
2012
- ],
2013
- defaultValue: "centered"
2014
- },
2015
- {
2016
- key: "loginSide",
2017
- label: "Brand Side",
2018
- type: "select",
2019
- choices: [
2020
- { value: "left", label: "Left" },
2021
- { value: "right", label: "Right" }
2022
- ],
2023
- defaultValue: "left"
2024
- },
2025
- {
2026
- key: "loginCard",
2027
- label: "Card",
2028
- type: "select",
2029
- choices: [
2030
- { value: "card", label: "Card" },
2031
- { value: "plain", label: "None" }
2032
- ],
2033
- defaultValue: "card"
2034
- },
2035
- {
2036
- key: "loginBg",
2037
- label: "Background",
2038
- type: "select",
2039
- choices: [
2040
- { value: "default", label: "Muted" },
2041
- { value: "subtle", label: "Gradient" },
2042
- { value: "none", label: "None" }
2043
- ],
2044
- defaultValue: "default"
2045
- },
2046
- {
2047
- key: "loginCardWidth",
2048
- label: "Width",
2049
- type: "select",
2050
- choices: [
2051
- { value: "sm", label: "Narrow" },
2052
- { value: "md", label: "Medium" },
2053
- { value: "lg", label: "Wide" }
2054
- ],
2055
- defaultValue: "sm"
2056
- }
2057
- ];
2058
- var TEMPLATE_DEFINITIONS = [
2059
- // ── DataGridView (nested under DataBodyTemplate) ─────────────────────────────
2060
- {
2061
- id: "table",
2062
- label: "Standard",
2063
- navigationSubgroupLabel: "Table",
2064
- group: "Table",
2065
- navigationGroup: "DataBodyTemplate",
2066
- layoutClassName: "layout-table",
2067
- exportComponent: "DataGridView",
2068
- exportKind: "data-grid",
2069
- preset: { radius: 0.125 },
2070
- options: topBarOptions,
2071
- preview: {
2072
- variant: "standard",
2073
- breadcrumb: "Data / Table",
2074
- title: "Users"
2075
- }
2076
- },
2077
- {
2078
- id: "table-infinity",
2079
- label: "Infinite Scroll",
2080
- group: "Table",
2081
- navigationGroup: "DataBodyTemplate",
2082
- navigationParent: "table",
2083
- layoutClassName: "layout-table-infinity",
2084
- exportComponent: "DataGridView",
2085
- exportKind: "data-grid",
2086
- preset: { radius: 0.125 },
2087
- preview: {
2088
- variant: "infinity",
2089
- breadcrumb: "Data / Table / Infinite Scroll",
2090
- title: "Users",
2091
- description: "gridkit DataGridInfinity"
2092
- },
2093
- options: topBarOptions
2094
- },
2095
- {
2096
- id: "table-drag",
2097
- label: "Row Drag",
2098
- group: "Table",
2099
- navigationGroup: "DataBodyTemplate",
2100
- navigationParent: "table",
2101
- layoutClassName: "layout-table-drag",
2102
- exportComponent: "DataGridView",
2103
- exportKind: "data-grid",
2104
- preset: { radius: 0.125 },
2105
- preview: {
2106
- variant: "drag",
2107
- breadcrumb: "Data / Table / Row Drag",
2108
- title: "Services",
2109
- description: "gridkit DataGridDrag"
2110
- },
2111
- options: topBarOptions
2112
- },
2113
- {
2114
- id: "table-card",
2115
- label: "Card Grid",
2116
- navigationSubgroupLabel: "Card",
2117
- group: "Table",
2118
- navigationGroup: "DataBodyTemplate",
2119
- layoutClassName: "layout-table-card",
2120
- exportComponent: "DataGridView",
2121
- exportKind: "data-grid-card",
2122
- preset: { radius: 0.375 },
2123
- preview: {
2124
- variant: "card",
2125
- breadcrumb: "Data / Table / Card Grid",
2126
- title: "User Cards",
2127
- description: "gridkit DataGridCard"
2128
- },
2129
- options: topBarOptions
2130
- },
2131
- {
2132
- id: "table-card-list",
2133
- label: "Card List",
2134
- group: "Table",
2135
- navigationGroup: "DataBodyTemplate",
2136
- navigationParent: "table-card",
2137
- layoutClassName: "layout-table-card-list",
2138
- exportComponent: "DataGridView",
2139
- exportKind: "data-grid-card",
2140
- preset: { radius: 0.375 },
2141
- preview: {
2142
- variant: "card-list",
2143
- breadcrumb: "Data / Table / Card List",
2144
- title: "User Cards",
2145
- description: "gridkit DataGridCard list mode"
2146
- },
2147
- options: topBarOptions
2148
- },
2149
- // ── DataBodyTemplate ─────────────────────────────────────────────────────────
2150
- {
2151
- id: "databody",
2152
- label: "Standard",
2153
- navigationSubgroupLabel: "Data View",
2154
- group: "Pages",
2155
- navigationGroup: "DataBodyTemplate",
2156
- layoutClassName: "layout-databody",
2157
- exportComponent: "DataBodyTemplate",
2158
- exportKind: "databody",
2159
- preset: { radius: 0.375 },
2160
- options: topBarOptions
2161
- },
2162
- {
2163
- id: "databody-detail",
2164
- label: "Detail",
2165
- group: "Pages",
2166
- navigationGroup: "DataBodyTemplate",
2167
- navigationParent: "databody",
2168
- layoutClassName: "layout-databody-detail",
2169
- exportComponent: "DataBodyTemplate",
2170
- exportKind: "databody",
2171
- preset: { radius: 0.375 },
2172
- options: topBarOptions
2173
- },
2174
- {
2175
- id: "databody-split",
2176
- label: "Split",
2177
- group: "Pages",
2178
- navigationGroup: "DataBodyTemplate",
2179
- navigationParent: "databody",
2180
- layoutClassName: "layout-databody-split",
2181
- exportComponent: "DataBodyTemplate",
2182
- exportKind: "databody",
2183
- preset: { radius: 0.375 },
2184
- options: topBarOptions
2185
- },
2186
- {
2187
- id: "tabbed",
2188
- label: "Tabbed",
2189
- group: "Pages",
2190
- navigationGroup: "DataBodyTemplate",
2191
- navigationParent: "databody",
2192
- layoutClassName: "layout-tabbed",
2193
- exportComponent: "DataBodyTemplate",
2194
- exportKind: "databody",
2195
- preset: { radius: 0.375 },
2196
- options: topBarOptions
2197
- },
2198
- {
2199
- id: "form",
2200
- label: "Form Horizontal",
2201
- navigationLabel: "Horizontal",
2202
- navigationSubgroupLabel: "Form",
2203
- group: "Pages",
2204
- navigationGroup: "DataBodyTemplate",
2205
- layoutClassName: "layout-form",
2206
- exportComponent: "DataBodyTemplate",
2207
- exportKind: "databody",
2208
- preset: { radius: 0.5 },
2209
- options: topBarOptions
2210
- },
2211
- {
2212
- id: "form-stacked",
2213
- label: "Form Stacked",
2214
- navigationLabel: "Stacked",
2215
- group: "Pages",
2216
- navigationGroup: "DataBodyTemplate",
2217
- navigationParent: "form",
2218
- layoutClassName: "layout-form-stacked",
2219
- exportComponent: "DataBodyTemplate",
2220
- exportKind: "databody",
2221
- preset: { radius: 0.5 },
2222
- options: topBarOptions
2223
- },
2224
- {
2225
- id: "form-inline",
2226
- label: "Form Inline",
2227
- navigationLabel: "Inline",
2228
- group: "Pages",
2229
- navigationGroup: "DataBodyTemplate",
2230
- navigationParent: "form",
2231
- layoutClassName: "layout-form-inline",
2232
- exportComponent: "DataBodyTemplate",
2233
- exportKind: "databody",
2234
- preset: { radius: 0.25 },
2235
- options: topBarOptions
2236
- },
2237
- {
2238
- id: "sectioned",
2239
- label: "Sectioned",
2240
- group: "Pages",
2241
- navigationGroup: "DataBodyTemplate",
2242
- layoutClassName: "layout-sectioned",
2243
- exportComponent: "DataBodyTemplate",
2244
- exportKind: "body-template",
2245
- preset: { radius: 0.5 },
2246
- options: topBarOptions
2247
- },
2248
- // ── Common ───────────────────────────────────────────────────────────────────
2249
- {
2250
- id: "typography",
2251
- label: "Typography",
2252
- navigationSubgroupLabel: "Typography",
2253
- group: "Design",
2254
- navigationGroup: "Common",
2255
- layoutClassName: "layout-typography",
2256
- exportComponent: "TypographyBodyTemplate",
2257
- exportKind: "body-template",
2258
- preset: { radius: 0.375 }
2259
- },
2260
- {
2261
- id: "colors",
2262
- label: "Colors",
2263
- navigationSubgroupLabel: "Colors",
2264
- group: "Design",
2265
- navigationGroup: "Common",
2266
- layoutClassName: "layout-colors",
2267
- exportComponent: "ColorsBodyTemplate",
2268
- exportKind: "body-template",
2269
- preset: { radius: 0.375 }
2270
- },
2271
- // ── FormWizardBodyTemplate ────────────────────────────────────────────────────
2272
- {
2273
- id: "form-wizard",
2274
- label: "Wizard",
2275
- group: "Pages",
2276
- navigationGroup: "FormWizardBodyTemplate",
2277
- layoutClassName: "layout-form-wizard",
2278
- exportComponent: "FormWizardBodyTemplate",
2279
- exportKind: "body-template",
2280
- preset: { radius: 0.5 },
2281
- options: topBarOptions
2282
- },
2283
- // ── LoginBodyTemplate ─────────────────────────────────────────────────────────
2284
- {
2285
- id: "login",
2286
- label: "Sign In",
2287
- navigationSubgroupLabel: "Auth",
2288
- group: "Auth",
2289
- navigationGroup: "LoginBodyTemplate",
2290
- layoutClassName: "layout-login",
2291
- exportComponent: "LoginBodyTemplate",
2292
- exportKind: "login",
2293
- preset: { radius: 0.5 },
2294
- options: loginOptions
2295
- },
2296
- {
2297
- id: "login-forgot",
2298
- label: "Forgot Password",
2299
- navigationLabel: "Forgot",
2300
- group: "Auth",
2301
- navigationGroup: "LoginBodyTemplate",
2302
- navigationParent: "login",
2303
- layoutClassName: "layout-login",
2304
- exportComponent: "LoginBodyTemplate",
2305
- exportKind: "login",
2306
- preset: { radius: 0.5 },
2307
- options: loginOptions
2308
- },
2309
- {
2310
- id: "login-reset",
2311
- label: "Reset Password",
2312
- navigationLabel: "Reset",
2313
- group: "Auth",
2314
- navigationGroup: "LoginBodyTemplate",
2315
- navigationParent: "login",
2316
- layoutClassName: "layout-login",
2317
- exportComponent: "LoginBodyTemplate",
2318
- exportKind: "login",
2319
- preset: { radius: 0.5 },
2320
- options: loginOptions
2321
- },
2322
- {
2323
- id: "login-otp",
2324
- label: "OTP Verification",
2325
- navigationLabel: "OTP",
2326
- group: "Auth",
2327
- navigationGroup: "LoginBodyTemplate",
2328
- navigationParent: "login",
2329
- layoutClassName: "layout-login",
2330
- exportComponent: "LoginBodyTemplate",
2331
- exportKind: "login",
2332
- preset: { radius: 0.5 },
2333
- options: loginOptions
2334
- }
2335
- ];
2336
- function getTemplateDefinition(id) {
2337
- return TEMPLATE_DEFINITIONS.find((definition) => definition.id === id);
2338
- }
2339
- function createTemplateOverrides() {
2340
- return TEMPLATE_DEFINITIONS.reduce(
2341
- (acc, definition) => {
2342
- acc[definition.id] = { ...definition.preset };
2343
- return acc;
2344
- },
2345
- {}
2346
- );
2347
- }
2348
- function DataGridView({
2349
- data,
2350
- columns,
2351
- getRowId = (_row, index) => String(index),
2352
- variant = "standard",
2353
- tableHeight = "100%",
2354
- rowHeight = 36,
2355
- tableWidthMode = "fill-last",
2356
- enableSorting = true,
2357
- enableColumnFilters,
2358
- emptyMessage = "No rows found",
2359
- headerLeft: headerLeft3,
2360
- headerRight: headerRight3,
2361
- pagination,
2362
- footer,
2363
- infinity,
2364
- drag,
2365
- card
2366
- }) {
2367
- const [orderedData, setOrderedData] = useState(data);
2368
- useEffect(() => {
2369
- setOrderedData(data);
2370
- }, [data]);
2371
- const dragColumnSize = drag?.dragColumnSize ?? 28;
2372
- const dragColumns = useMemo(
2373
- () => [
2374
- {
2375
- id: "drag",
2376
- size: dragColumnSize,
2377
- minSize: dragColumnSize,
2378
- maxSize: dragColumnSize,
2379
- enableResizing: false,
2380
- enableSorting: false,
2381
- header: () => null,
2382
- cell: () => /* @__PURE__ */ jsx(DragHandleCell, {}),
2383
- meta: { align: "center" }
2384
- },
2385
- ...columns
2386
- ],
2387
- [columns, dragColumnSize]
2388
- );
2389
- const handleRowReorder = (rows) => {
2390
- setOrderedData(rows);
2391
- drag?.onRowReorder?.(rows);
2392
- };
2393
- if (variant === "infinity") {
2394
- return /* @__PURE__ */ jsx(
2395
- DataGridInfinity,
2396
- {
2397
- data: infinity?.data ?? data,
2398
- columns,
2399
- getRowId,
2400
- tableHeight,
2401
- rowHeight,
2402
- enableSorting,
2403
- enableColumnFilters,
2404
- tableWidthMode,
2405
- headerLeft: headerLeft3,
2406
- headerRight: headerRight3,
2407
- hasNextPage: infinity?.hasNextPage ?? false,
2408
- isFetchingNextPage: infinity?.isFetchingNextPage ?? false,
2409
- fetchNextPage: infinity?.fetchNextPage ?? (() => void 0),
2410
- emptyMessage,
2411
- tableKey: infinity?.tableKey
2412
- }
2413
- );
2414
- }
2415
- if (variant === "drag") {
2416
- return /* @__PURE__ */ jsx(
2417
- DataGridDrag,
2418
- {
2419
- data: orderedData,
2420
- columns: dragColumns,
2421
- getRowId,
2422
- onRowReorder: handleRowReorder,
2423
- tableHeight,
2424
- rowHeight,
2425
- columnSizing: { drag: dragColumnSize },
2426
- tableWidthMode,
2427
- headerLeft: headerLeft3,
2428
- headerRight: headerRight3,
2429
- emptyMessage,
2430
- classNames: {
2431
- cell: "[&[data-col-id=drag]]:px-1",
2432
- headerCell: "[&[data-col-id=drag]]:px-1"
2433
- }
2434
- }
2435
- );
2436
- }
2437
- if (variant === "card" || variant === "card-list") {
2438
- if (!card?.renderCard) {
2439
- throw new Error("DataGridView card variants require card.renderCard.");
2440
- }
2441
- return /* @__PURE__ */ jsx(
2442
- DataGridCard,
2443
- {
2444
- data,
2445
- columns,
2446
- getRowId,
2447
- tableHeight,
2448
- rowHeight,
2449
- enableSorting,
2450
- enableColumnFilters,
2451
- tableWidthMode,
2452
- headerLeft: headerLeft3,
2453
- headerRight: headerRight3,
2454
- cardColumns: card?.cardColumns ?? (variant === "card-list" ? 1 : void 0),
2455
- minCardWidth: card?.minCardWidth ?? 220,
2456
- minColumns: card?.minColumns ?? (variant === "card-list" ? 1 : 2),
2457
- renderCard: card.renderCard
2458
- }
2459
- );
2460
- }
2461
- return /* @__PURE__ */ jsx(
2462
- DataGrid,
2463
- {
2464
- data,
2465
- columns,
2466
- getRowId,
2467
- tableHeight,
2468
- rowHeight,
2469
- enableSorting,
2470
- enableColumnFilters,
2471
- tableWidthMode,
2472
- headerLeft: headerLeft3,
2473
- headerRight: headerRight3,
2474
- pagination: pagination === false ? void 0 : pagination,
2475
- footer,
2476
- emptyMessage
2477
- }
2478
- );
2479
- }
2480
1968
  function Root({ children, className, style }) {
2481
1969
  return /* @__PURE__ */ jsx(
2482
1970
  "div",
@@ -2642,6 +2130,71 @@ var DataPage = Object.assign(Root, {
2642
2130
  GroupBody,
2643
2131
  Footer
2644
2132
  });
2133
+ var DashboardPanel = forwardRef(function DashboardPanel2({
2134
+ title,
2135
+ description,
2136
+ loading,
2137
+ error,
2138
+ transparent,
2139
+ editable,
2140
+ className,
2141
+ style,
2142
+ children,
2143
+ headerRight
2144
+ }, ref) {
2145
+ return /* @__PURE__ */ jsxs(
2146
+ "div",
2147
+ {
2148
+ ref,
2149
+ className: cn(
2150
+ "group flex h-full flex-col overflow-hidden",
2151
+ transparent ? "" : "rounded-(--radius) border bg-card text-card-foreground",
2152
+ editable && "ring-1 ring-border/60 ring-inset",
2153
+ className
2154
+ ),
2155
+ style,
2156
+ children: [
2157
+ (title || headerRight || editable) && /* @__PURE__ */ jsxs("div", { className: "flex shrink-0 items-center gap-2 pl-3 pr-1.5 py-2", children: [
2158
+ editable && /* @__PURE__ */ jsx("div", { className: "shrink-0 cursor-grab active:cursor-grabbing select-none text-muted-foreground/40 hover:text-muted-foreground/70 transition-colors -ml-1 px-0.5", children: /* @__PURE__ */ jsx(GripHorizontal, { className: "h-3.5 w-3.5" }) }),
2159
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
2160
+ title && /* @__PURE__ */ jsx("p", { className: "truncate text-xs font-medium text-card-foreground", children: title }),
2161
+ description && /* @__PURE__ */ jsx("p", { className: "truncate text-[11px] text-muted-foreground", children: description })
2162
+ ] }),
2163
+ headerRight && /* @__PURE__ */ jsx("div", { className: "shrink-0 flex items-center gap-1 opacity-0 group-hover:opacity-100 transition-opacity duration-150", children: headerRight })
2164
+ ] }),
2165
+ /* @__PURE__ */ jsxs("div", { className: "relative flex-1 min-h-0 p-3", children: [
2166
+ loading && /* @__PURE__ */ jsx("div", { className: "absolute inset-0 flex items-center justify-center bg-card/70 z-10", children: /* @__PURE__ */ jsx("div", { className: "h-4 w-4 animate-spin rounded-full border-2 border-primary border-t-transparent" }) }),
2167
+ error && /* @__PURE__ */ jsx("div", { className: "flex h-full items-center justify-center", children: /* @__PURE__ */ jsx("p", { className: "text-xs text-destructive", children: error }) }),
2168
+ !error && children
2169
+ ] })
2170
+ ]
2171
+ }
2172
+ );
2173
+ });
2174
+ function DashboardBodyTemplate({
2175
+ theme,
2176
+ className,
2177
+ title,
2178
+ description,
2179
+ topBar,
2180
+ toolbar,
2181
+ variableBar,
2182
+ children,
2183
+ contentClassName
2184
+ }) {
2185
+ return /* @__PURE__ */ jsxs(DataPage, { className: cn("layout-dashboard", className), style: theme, children: [
2186
+ topBar && /* @__PURE__ */ jsx("div", { className: "shrink-0", children: topBar }),
2187
+ (title || toolbar) && /* @__PURE__ */ jsx("header", { className: "shrink-0 border-b px-(--dk-page-padding-x) py-(--dk-page-padding-y)", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center justify-between gap-3", children: [
2188
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
2189
+ title && /* @__PURE__ */ jsx("h1", { className: "text-sm font-semibold truncate", children: title }),
2190
+ description && /* @__PURE__ */ jsx("p", { className: "mt-0.5 text-xs text-muted-foreground", children: description })
2191
+ ] }),
2192
+ toolbar && /* @__PURE__ */ jsx("div", { className: "flex items-center gap-2 shrink-0", children: toolbar })
2193
+ ] }) }),
2194
+ variableBar && /* @__PURE__ */ jsx("div", { className: "shrink-0 flex flex-wrap items-center gap-2 px-(--dk-page-padding-x) py-1.5", children: variableBar }),
2195
+ /* @__PURE__ */ jsx("div", { className: cn("flex-1 min-h-0 overflow-auto px-[calc(var(--dk-page-padding-x)-0.5rem)] pt-0 pb-(--dk-page-padding-y)", contentClassName), children })
2196
+ ] });
2197
+ }
2645
2198
  function DataBodyTab(_props) {
2646
2199
  return null;
2647
2200
  }
@@ -2920,437 +2473,297 @@ var DataBodyTemplate = Object.assign(Root2, {
2920
2473
  Row: DataBodyRow,
2921
2474
  Field: DataBodyField
2922
2475
  });
2923
- function Breadcrumb({ className, ...props }) {
2924
- return /* @__PURE__ */ jsx(
2925
- "nav",
2926
- {
2927
- "aria-label": "breadcrumb",
2928
- "data-slot": "breadcrumb",
2929
- className: cn(className),
2930
- ...props
2931
- }
2932
- );
2476
+ function useIsNarrow() {
2477
+ const [narrow, setNarrow] = useState(false);
2478
+ useEffect(() => {
2479
+ const mql = window.matchMedia("(max-width: 1023px)");
2480
+ setNarrow(mql.matches);
2481
+ const handler = (e) => setNarrow(e.matches);
2482
+ mql.addEventListener("change", handler);
2483
+ return () => mql.removeEventListener("change", handler);
2484
+ }, []);
2485
+ return narrow;
2933
2486
  }
2934
- function BreadcrumbList({ className, ...props }) {
2935
- return /* @__PURE__ */ jsx(
2936
- "ol",
2487
+ function BrowseBodyTemplate({
2488
+ theme,
2489
+ className,
2490
+ topBar,
2491
+ title,
2492
+ description,
2493
+ actions,
2494
+ sidebar,
2495
+ sidebarTitle = "Filters",
2496
+ sidebarWidth = "18rem",
2497
+ toolbar,
2498
+ footer,
2499
+ contentClassName,
2500
+ children
2501
+ }) {
2502
+ const isNarrow = useIsNarrow();
2503
+ const hasHeader = title || description || actions;
2504
+ return /* @__PURE__ */ jsxs(DataPage, { className: cn("layout-browse", className), style: theme, children: [
2505
+ topBar && /* @__PURE__ */ jsx("div", { className: "shrink-0", children: topBar }),
2506
+ hasHeader && /* @__PURE__ */ jsxs(DataPage.Header, { children: [
2507
+ /* @__PURE__ */ jsx(DataPage.TitleBlock, { title, description }),
2508
+ /* @__PURE__ */ jsx(DataPage.Actions, { children: actions })
2509
+ ] }),
2510
+ /* @__PURE__ */ jsxs(DataPage.Content, { padding: "none", className: "flex flex-col overflow-hidden", children: [
2511
+ (toolbar || isNarrow) && /* @__PURE__ */ jsxs("div", { className: "flex shrink-0 items-center gap-2 border-b px-(--dk-page-padding-x) py-2", children: [
2512
+ isNarrow && /* @__PURE__ */ jsxs(Sheet, { children: [
2513
+ /* @__PURE__ */ jsxs(
2514
+ SheetTrigger,
2515
+ {
2516
+ render: /* @__PURE__ */ jsx(Button, { variant: "outline", size: "sm", className: "shrink-0 gap-1.5" }),
2517
+ children: [
2518
+ /* @__PURE__ */ jsx(SlidersHorizontal, { className: "h-3.5 w-3.5" }),
2519
+ sidebarTitle
2520
+ ]
2521
+ }
2522
+ ),
2523
+ /* @__PURE__ */ jsxs(SheetContent, { side: "left", className: "flex flex-col gap-0 p-0", children: [
2524
+ /* @__PURE__ */ jsx(SheetHeader, { className: "shrink-0 border-b px-4 py-3", children: /* @__PURE__ */ jsx(SheetTitle, { children: sidebarTitle }) }),
2525
+ /* @__PURE__ */ jsx(ScrollArea, { className: "flex-1", children: /* @__PURE__ */ jsx("div", { className: "p-4", children: sidebar }) })
2526
+ ] })
2527
+ ] }),
2528
+ toolbar && /* @__PURE__ */ jsx("div", { className: "flex min-w-0 flex-1 items-center gap-2", children: toolbar })
2529
+ ] }),
2530
+ /* @__PURE__ */ jsxs("div", { className: "flex min-h-0 flex-1 overflow-hidden", children: [
2531
+ !isNarrow && /* @__PURE__ */ jsx(
2532
+ "aside",
2533
+ {
2534
+ className: "shrink-0 overflow-hidden border-r",
2535
+ style: { width: sidebarWidth },
2536
+ children: /* @__PURE__ */ jsx(ScrollArea, { className: "h-full", children: /* @__PURE__ */ jsx("div", { className: "px-(--dk-page-padding-x) py-(--dk-page-padding-y)", children: sidebar }) })
2537
+ }
2538
+ ),
2539
+ /* @__PURE__ */ jsx(
2540
+ "div",
2541
+ {
2542
+ className: cn(
2543
+ "min-w-0 flex-1 overflow-hidden px-(--dk-page-padding-x) py-(--dk-page-padding-y)",
2544
+ "[&_.dg-shell]:h-full [&_.dg-table-stack]:flex-1 [&_.dg-table-stack]:min-h-0",
2545
+ "[&_.dg-card-container]:flex-1 [&_.dg-card-container]:min-h-0 [&_.dg-card-container]:overflow-auto",
2546
+ contentClassName
2547
+ ),
2548
+ children
2549
+ }
2550
+ )
2551
+ ] })
2552
+ ] }),
2553
+ footer && /* @__PURE__ */ jsx(DataPage.Footer, { children: footer })
2554
+ ] });
2555
+ }
2556
+ function DetailBodyHeader({
2557
+ eyebrow,
2558
+ title,
2559
+ description,
2560
+ status,
2561
+ actions,
2562
+ compact,
2563
+ className
2564
+ }) {
2565
+ return /* @__PURE__ */ jsxs(DataPage.Header, { className, children: [
2566
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
2567
+ eyebrow && /* @__PURE__ */ jsx("div", { className: "mb-1 text-[11px] font-medium uppercase tracking-wider text-muted-foreground", children: eyebrow }),
2568
+ /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-wrap items-center gap-2", children: [
2569
+ title && /* @__PURE__ */ jsx("h1", { className: cn("min-w-0 truncate font-semibold", compact ? "text-base" : "text-lg"), children: title }),
2570
+ status && /* @__PURE__ */ jsx("div", { className: "shrink-0", children: status })
2571
+ ] }),
2572
+ description && /* @__PURE__ */ jsx("p", { className: "mt-1 text-sm text-muted-foreground", children: description })
2573
+ ] }),
2574
+ /* @__PURE__ */ jsx(DataPage.Actions, { children: actions })
2575
+ ] });
2576
+ }
2577
+ function DetailBodyTab(_props) {
2578
+ return null;
2579
+ }
2580
+ function isDetailBodyTab(node) {
2581
+ return Boolean(node && typeof node === "object" && "type" in node && node.type === DetailBodyTab);
2582
+ }
2583
+ function DetailBodySection({
2584
+ title,
2585
+ description,
2586
+ actions,
2587
+ surface = "plain",
2588
+ className,
2589
+ children
2590
+ }) {
2591
+ return /* @__PURE__ */ jsxs(
2592
+ "section",
2937
2593
  {
2938
- "data-slot": "breadcrumb-list",
2939
2594
  className: cn(
2940
- "flex flex-wrap items-center gap-1.5 text-sm wrap-break-word text-muted-foreground",
2595
+ "min-h-0",
2596
+ surface === "card" && "rounded-(--radius) border bg-card p-(--dk-panel-gap) text-card-foreground shadow-sm",
2597
+ surface === "bordered" && "rounded-(--radius) border p-(--dk-panel-gap)",
2941
2598
  className
2942
2599
  ),
2943
- ...props
2600
+ children: [
2601
+ (title || description || actions) && /* @__PURE__ */ jsxs("div", { className: "mb-3 flex items-start justify-between gap-3", children: [
2602
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
2603
+ title && /* @__PURE__ */ jsx("h2", { className: "text-sm font-semibold", children: title }),
2604
+ description && /* @__PURE__ */ jsx("p", { className: "mt-0.5 text-xs text-muted-foreground", children: description })
2605
+ ] }),
2606
+ actions && /* @__PURE__ */ jsx("div", { className: "shrink-0", children: actions })
2607
+ ] }),
2608
+ children
2609
+ ]
2944
2610
  }
2945
2611
  );
2946
2612
  }
2947
- function BreadcrumbItem({ className, ...props }) {
2948
- return /* @__PURE__ */ jsx(
2949
- "li",
2950
- {
2951
- "data-slot": "breadcrumb-item",
2952
- className: cn("inline-flex items-center gap-1", className),
2953
- ...props
2954
- }
2955
- );
2613
+ function renderChildren(nodes) {
2614
+ return Children.toArray(nodes).map((child, i) => /* @__PURE__ */ jsx(Fragment, { children: child }, i));
2956
2615
  }
2957
- function BreadcrumbLink({
2616
+ function DetailBodyTemplateRoot({
2617
+ variant = "record",
2618
+ theme,
2958
2619
  className,
2959
- render,
2960
- ...props
2620
+ topBar,
2621
+ header,
2622
+ lead,
2623
+ eyebrow,
2624
+ title,
2625
+ description,
2626
+ status,
2627
+ actions,
2628
+ media,
2629
+ aside,
2630
+ summary,
2631
+ stickyAside = true,
2632
+ contentClassName,
2633
+ mediaClassName,
2634
+ asideClassName,
2635
+ children
2961
2636
  }) {
2962
- return useRender({
2963
- defaultTagName: "a",
2964
- props: mergeProps(
2637
+ const childArray = useMemo(() => Children.toArray(children), [children]);
2638
+ const tabs = childArray.filter(isDetailBodyTab);
2639
+ const hasTabs = tabs.length > 0;
2640
+ const [activeTab, setActiveTab] = useState(() => tabs[0]?.props.id ?? "");
2641
+ const selectedTab = tabs.find((tab) => tab.props.id === activeTab) ?? tabs[0];
2642
+ const summarySlot = summary ? /* @__PURE__ */ jsx("div", { className: "min-h-0 rounded-(--radius) border bg-card p-(--dk-panel-gap) text-card-foreground", children: summary }) : null;
2643
+ const mediaSlot = media ? /* @__PURE__ */ jsx("div", { className: cn("min-h-0 overflow-hidden rounded-(--radius) border bg-card", mediaClassName), children: media }) : null;
2644
+ const leadGridClass = variant === "media" ? "xl:grid-cols-[minmax(0,1.35fr)_minmax(18rem,0.65fr)]" : "xl:grid-cols-2";
2645
+ const defaultHeader = eyebrow || title || description || status || actions ? /* @__PURE__ */ jsx(
2646
+ DetailBodyHeader,
2647
+ {
2648
+ eyebrow,
2649
+ title,
2650
+ description,
2651
+ status,
2652
+ actions
2653
+ }
2654
+ ) : null;
2655
+ const defaultLead = media || summary ? /* @__PURE__ */ jsxs("div", { className: cn("grid gap-(--dk-panel-gap)", leadGridClass), children: [
2656
+ mediaSlot,
2657
+ summarySlot
2658
+ ] }) : null;
2659
+ const body = hasTabs ? /* @__PURE__ */ jsxs("div", { className: "min-h-0", children: [
2660
+ /* @__PURE__ */ jsx(DataPage.Tabs, { children: tabs.map((tab) => /* @__PURE__ */ jsx(
2661
+ DataPage.Tab,
2965
2662
  {
2966
- className: cn("transition-colors hover:text-foreground", className)
2663
+ active: (selectedTab?.props.id ?? "") === tab.props.id,
2664
+ count: tab.props.count,
2665
+ disabled: tab.props.disabled,
2666
+ onClick: () => setActiveTab(tab.props.id),
2667
+ children: tab.props.label
2967
2668
  },
2968
- props
2669
+ tab.props.id
2670
+ )) }),
2671
+ /* @__PURE__ */ jsx("div", { className: "pt-(--dk-panel-gap)", children: selectedTab?.props.children })
2672
+ ] }) : /* @__PURE__ */ jsx("div", { className: "space-y-(--dk-panel-gap)", children: renderChildren(children) });
2673
+ const leadSlot = lead ?? defaultLead;
2674
+ const outsideAsideSlot = variant === "full" ? null : aside;
2675
+ const insideAsideSlot = variant === "full" ? aside : null;
2676
+ const hasRecordInspector = Boolean(leadSlot);
2677
+ const hasFullLeadArea = Boolean(leadSlot || insideAsideSlot);
2678
+ const layout = {
2679
+ media: /* @__PURE__ */ jsxs(Fragment$1, { children: [
2680
+ leadSlot && /* @__PURE__ */ jsx("div", { className: "mb-(--dk-panel-gap)", children: leadSlot }),
2681
+ body
2682
+ ] }),
2683
+ record: /* @__PURE__ */ jsxs(
2684
+ "div",
2685
+ {
2686
+ className: cn(
2687
+ "grid gap-(--dk-panel-gap)",
2688
+ hasRecordInspector && "xl:grid-cols-[minmax(28rem,1fr)_minmax(14rem,18rem)]"
2689
+ ),
2690
+ children: [
2691
+ /* @__PURE__ */ jsx("div", { className: "min-w-0", children: body }),
2692
+ hasRecordInspector && /* @__PURE__ */ jsx("div", { className: "space-y-(--dk-panel-gap)", children: leadSlot })
2693
+ ]
2694
+ }
2969
2695
  ),
2970
- render,
2971
- state: {
2972
- slot: "breadcrumb-link"
2973
- }
2974
- });
2975
- }
2976
- function BreadcrumbPage({ className, ...props }) {
2977
- return /* @__PURE__ */ jsx(
2978
- "span",
2979
- {
2980
- "data-slot": "breadcrumb-page",
2981
- role: "link",
2982
- "aria-disabled": "true",
2983
- "aria-current": "page",
2984
- className: cn("font-normal text-foreground", className),
2985
- ...props
2986
- }
2987
- );
2988
- }
2989
- function BreadcrumbSeparator({
2990
- children,
2991
- className,
2992
- ...props
2993
- }) {
2994
- return /* @__PURE__ */ jsx(
2995
- "li",
2996
- {
2997
- "data-slot": "breadcrumb-separator",
2998
- role: "presentation",
2999
- "aria-hidden": "true",
3000
- className: cn("[&>svg]:size-3.5", className),
3001
- ...props,
3002
- children: children ?? /* @__PURE__ */ jsx(ChevronRightIcon, {})
3003
- }
3004
- );
3005
- }
3006
- function PageBreadcrumb({ items }) {
3007
- return /* @__PURE__ */ jsx(Breadcrumb, { children: /* @__PURE__ */ jsx(BreadcrumbList, { className: "text-xs gap-1", children: items.map((item, i) => {
3008
- const isLast = i === items.length - 1;
3009
- const label = typeof item === "string" ? item : item.label;
3010
- const href = typeof item === "string" ? void 0 : item.href;
3011
- return /* @__PURE__ */ jsxs(React2__default.Fragment, { children: [
3012
- i > 0 && /* @__PURE__ */ jsx(BreadcrumbSeparator, {}),
3013
- /* @__PURE__ */ jsx(BreadcrumbItem, { children: isLast ? /* @__PURE__ */ jsx(BreadcrumbPage, { className: "text-xs", children: label }) : href ? /* @__PURE__ */ jsx(BreadcrumbLink, { href, className: "text-xs", children: label }) : /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: label }) })
3014
- ] }, i);
3015
- }) }) });
3016
- }
3017
- function normalizeBreadcrumb(left) {
3018
- if (typeof left === "string") {
3019
- const items = left.split("/").map((s) => s.trim()).filter(Boolean);
3020
- return /* @__PURE__ */ jsx(PageBreadcrumb, { items });
3021
- }
3022
- return left;
3023
- }
3024
- var bgClassMap = {
3025
- muted: "bg-muted",
3026
- card: "bg-card",
3027
- transparent: ""
3028
- };
3029
- function buildTopBar(opts) {
3030
- if (opts.topBarShow === "hide") return void 0;
3031
- return /* @__PURE__ */ jsx(
3032
- PageTopBar,
3033
- {
3034
- left: normalizeBreadcrumb(opts.left),
3035
- right: opts.right,
3036
- variant: opts.topBarVariant ?? "ghost",
3037
- className: bgClassMap[opts.topBarBg ?? "transparent"] ?? ""
3038
- }
3039
- );
3040
- }
3041
- function PageTopBar({
3042
- left,
3043
- right,
3044
- variant = "ghost",
3045
- height = "var(--dk-toolbar-height)",
3046
- className,
3047
- style,
3048
- children
3049
- }) {
3050
- return /* @__PURE__ */ jsxs(
3051
- "div",
3052
- {
3053
- className: cn(
3054
- "flex shrink-0 items-center justify-between gap-4 px-(--dk-page-padding-x)",
3055
- variant === "default" && "border-b",
3056
- className
2696
+ full: /* @__PURE__ */ jsxs(Fragment$1, { children: [
2697
+ hasFullLeadArea && /* @__PURE__ */ jsxs(
2698
+ "div",
2699
+ {
2700
+ className: cn(
2701
+ "mb-(--dk-panel-gap) grid gap-(--dk-panel-gap)",
2702
+ insideAsideSlot && "xl:grid-cols-[minmax(0,1fr)_minmax(18rem,24rem)]"
2703
+ ),
2704
+ children: [
2705
+ leadSlot && /* @__PURE__ */ jsx("div", { className: "space-y-(--dk-panel-gap)", children: leadSlot }),
2706
+ insideAsideSlot && /* @__PURE__ */ jsx("div", { className: cn("min-h-0 rounded-(--radius) border bg-card p-(--dk-panel-gap)", asideClassName), children: insideAsideSlot })
2707
+ ]
2708
+ }
3057
2709
  ),
3058
- style: { height, ...style },
3059
- children: [
3060
- /* @__PURE__ */ jsx("div", { className: "flex min-w-0 items-center text-xs text-muted-foreground", children: normalizeBreadcrumb(left ?? children) }),
3061
- right && /* @__PURE__ */ jsx("div", { className: "flex shrink-0 items-center gap-2", children: right })
3062
- ]
3063
- }
3064
- );
3065
- }
3066
- var users = [
3067
- {
3068
- id: "1",
3069
- name: "Sarah Kim",
3070
- email: "sarah@acme.com",
3071
- role: "Admin",
3072
- status: "active",
3073
- joined: "Jan 12, 2024"
3074
- },
3075
- {
3076
- id: "2",
3077
- name: "Marcus Lee",
3078
- email: "marcus@acme.com",
3079
- role: "Editor",
3080
- status: "active",
3081
- joined: "Feb 3, 2024"
3082
- },
3083
- {
3084
- id: "3",
3085
- name: "Ji-Yeon Park",
3086
- email: "jiyeon@acme.com",
3087
- role: "Viewer",
3088
- status: "inactive",
3089
- joined: "Mar 18, 2024"
3090
- },
3091
- {
3092
- id: "4",
3093
- name: "Alex Chen",
3094
- email: "alex@acme.com",
3095
- role: "Editor",
3096
- status: "pending",
3097
- joined: "Apr 7, 2024"
3098
- }
3099
- ];
3100
- var statusVariant = { active: "default", pending: "secondary", inactive: "outline" };
3101
- var userColumns = [
3102
- {
3103
- id: "name",
3104
- accessorKey: "name",
3105
- header: "Name",
3106
- cell: ({ row }) => /* @__PURE__ */ jsx("span", { className: "font-medium", children: row.original.name })
3107
- },
3108
- {
3109
- id: "email",
3110
- accessorKey: "email",
3111
- header: "Email",
3112
- cell: ({ row }) => /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: row.original.email })
3113
- },
3114
- {
3115
- id: "role",
3116
- accessorKey: "role",
3117
- header: "Role",
3118
- cell: ({ row }) => /* @__PURE__ */ jsx(Badge, { variant: "outline", className: "text-xs font-normal", children: row.original.role })
3119
- },
3120
- {
3121
- id: "status",
3122
- accessorKey: "status",
3123
- header: "Status",
3124
- cell: ({ row }) => /* @__PURE__ */ jsx(Badge, { variant: statusVariant[row.original.status], className: "text-xs capitalize", children: row.original.status })
3125
- },
3126
- {
3127
- id: "joined",
3128
- accessorKey: "joined",
3129
- header: "Joined",
3130
- cell: ({ row }) => /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: row.original.joined })
3131
- }
3132
- ];
3133
- var headerLeft = (table) => /* @__PURE__ */ jsx(GlobalSearch, { table, placeholder: "Search..." });
3134
- var headerRight = () => /* @__PURE__ */ jsxs(Button, { size: "sm", className: "h-8 gap-1.5 text-xs", children: [
3135
- /* @__PURE__ */ jsx(Plus, { className: "h-3.5 w-3.5" }),
3136
- "Add User"
3137
- ] });
3138
- function UserTable() {
3139
- return /* @__PURE__ */ jsx(
3140
- DataGrid,
3141
- {
3142
- data: users,
3143
- columns: userColumns,
3144
- getRowId: (row) => row.id,
3145
- tableHeight: 420,
3146
- rowHeight: 36,
3147
- enableSorting: true,
3148
- tableWidthMode: "fill-last",
3149
- headerLeft,
3150
- headerRight,
3151
- pagination: { pageSize: 10 },
3152
- footer: (table) => /* @__PURE__ */ jsxs("div", { className: "flex h-9 items-center justify-between px-1 text-xs text-muted-foreground", children: [
3153
- /* @__PURE__ */ jsxs("span", { children: [
3154
- users.length,
3155
- " results"
3156
- ] }),
3157
- /* @__PURE__ */ jsx(DataGridPaginationCompact, { table })
3158
- ] })
3159
- }
3160
- );
3161
- }
3162
- function UserCards() {
3163
- return /* @__PURE__ */ jsx(
3164
- DataGridCard,
3165
- {
3166
- data: users,
3167
- columns: userColumns,
3168
- getRowId: (row) => row.id,
3169
- tableHeight: 420,
3170
- rowHeight: 36,
3171
- enableSorting: true,
3172
- tableWidthMode: "fill-last",
3173
- headerLeft,
3174
- headerRight,
3175
- minCardWidth: 220,
3176
- minColumns: 2,
3177
- renderCard: (row) => /* @__PURE__ */ jsx(Card, { size: "sm", className: "h-full rounded-lg border border-border shadow-sm ring-0", children: /* @__PURE__ */ jsxs(CardContent, { className: "py-3", children: [
3178
- /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-3", children: [
3179
- /* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
3180
- /* @__PURE__ */ jsx("p", { className: "truncate text-sm font-medium", children: row.original.name }),
3181
- /* @__PURE__ */ jsx("p", { className: "truncate text-xs text-muted-foreground", children: row.original.email })
3182
- ] }),
3183
- /* @__PURE__ */ jsx(Badge, { variant: statusVariant[row.original.status], className: "text-xs capitalize", children: row.original.status })
3184
- ] }),
3185
- /* @__PURE__ */ jsxs("div", { className: "mt-4 grid grid-cols-2 gap-3 text-xs", children: [
3186
- /* @__PURE__ */ jsxs("div", { children: [
3187
- /* @__PURE__ */ jsx("p", { className: "text-muted-foreground", children: "Role" }),
3188
- /* @__PURE__ */ jsx("p", { className: "mt-0.5 font-medium", children: row.original.role })
3189
- ] }),
3190
- /* @__PURE__ */ jsxs("div", { children: [
3191
- /* @__PURE__ */ jsx("p", { className: "text-muted-foreground", children: "Joined" }),
3192
- /* @__PURE__ */ jsx("p", { className: "mt-0.5 font-medium", children: row.original.joined })
3193
- ] })
3194
- ] })
3195
- ] }) })
3196
- }
3197
- );
3198
- }
3199
- var recentColumns = [
3200
- {
3201
- id: "name",
3202
- accessorKey: "name",
3203
- header: "Name",
3204
- cell: ({ row }) => /* @__PURE__ */ jsx("span", { className: "font-medium", children: row.original.name })
3205
- },
3206
- {
3207
- id: "role",
3208
- accessorKey: "role",
3209
- header: "Role",
3210
- cell: ({ row }) => /* @__PURE__ */ jsx(Badge, { variant: "outline", className: "text-xs font-normal", children: row.original.role })
3211
- },
3212
- {
3213
- id: "status",
3214
- accessorKey: "status",
3215
- header: "Status",
3216
- cell: ({ row }) => /* @__PURE__ */ jsx(Badge, { variant: statusVariant[row.original.status], className: "text-xs capitalize", children: row.original.status })
3217
- },
3218
- {
3219
- id: "joined",
3220
- accessorKey: "joined",
3221
- header: "Joined",
3222
- cell: ({ row }) => /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: row.original.joined })
3223
- }
3224
- ];
3225
- function OverviewContent() {
3226
- return /* @__PURE__ */ jsxs(Fragment$1, { children: [
3227
- /* @__PURE__ */ jsx(
3228
- DataBodyTemplate.Group,
3229
- {
3230
- layout: "horizontal",
3231
- title: "Workspace",
3232
- description: "Basic workspace information and plan details.",
3233
- children: /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
3234
- /* @__PURE__ */ jsx(DataBodyTemplate.Row, { label: "Workspace name", children: /* @__PURE__ */ jsx("span", { className: "text-sm", children: "Acme Corp" }) }),
3235
- /* @__PURE__ */ jsx(DataBodyTemplate.Row, { label: "Plan", children: /* @__PURE__ */ jsx(Badge, { variant: "secondary", className: "text-xs", children: "Pro" }) }),
3236
- /* @__PURE__ */ jsx(DataBodyTemplate.Row, { label: "Region", children: /* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: "us-east-1" }) }),
3237
- /* @__PURE__ */ jsx(DataBodyTemplate.Row, { label: "SSO", children: /* @__PURE__ */ jsx(Switch, { defaultChecked: true }) })
3238
- ] })
3239
- }
3240
- ),
3241
- /* @__PURE__ */ jsx(DataBodyTemplate.Group, { layout: "stacked", title: "Members", description: "Recently added members.", children: /* @__PURE__ */ jsx(
3242
- DataGrid,
2710
+ body
2711
+ ] })
2712
+ };
2713
+ return /* @__PURE__ */ jsxs(DataPage, { className: cn("layout-detail", className), style: theme, "data-detail-variant": variant, children: [
2714
+ topBar && /* @__PURE__ */ jsx("div", { className: "shrink-0", children: topBar }),
2715
+ header ?? defaultHeader,
2716
+ /* @__PURE__ */ jsx(DataPage.Content, { padding: "none", className: "overflow-hidden", children: /* @__PURE__ */ jsxs(
2717
+ "div",
3243
2718
  {
3244
- data: users,
3245
- columns: recentColumns,
3246
- getRowId: (row) => row.id,
3247
- tableHeight: 220,
3248
- rowHeight: 36,
3249
- tableWidthMode: "fill-last",
3250
- headerRight: () => /* @__PURE__ */ jsxs(Button, { size: "sm", className: "h-8 gap-1.5 text-xs", children: [
3251
- /* @__PURE__ */ jsx(Plus, { className: "h-3.5 w-3.5" }),
3252
- "Invite"
3253
- ] })
3254
- }
3255
- ) })
3256
- ] });
3257
- }
3258
- function CustomContent() {
3259
- return /* @__PURE__ */ jsx(Card, { className: "rounded-lg border border-border ring-0", children: /* @__PURE__ */ jsx(CardContent, { className: "grid gap-3 p-4 md:grid-cols-3", children: ["Header", "Tabs", "Content"].map((label) => /* @__PURE__ */ jsxs("div", { className: "rounded-lg border bg-muted/30 p-3", children: [
3260
- /* @__PURE__ */ jsx("p", { className: "text-sm font-medium", children: label }),
3261
- /* @__PURE__ */ jsx("p", { className: "mt-1 text-xs text-muted-foreground", children: "ReactNode slot" })
3262
- ] }, label)) }) });
3263
- }
3264
- function DataBodyTemplateDemo({ theme, topBarShow, topBarVariant, topBarBg }) {
3265
- return /* @__PURE__ */ jsxs(
3266
- DataBodyTemplate,
3267
- {
3268
- theme,
3269
- topBar: buildTopBar({ topBarShow, topBarVariant, topBarBg, left: "Design / Body Template" }),
3270
- title: "Body Template",
3271
- description: "Compound body shell with optional tabs and arbitrary content",
3272
- children: [
3273
- /* @__PURE__ */ jsx(DataBodyTemplate.Tab, { id: "overview", label: "Overview", children: /* @__PURE__ */ jsx(OverviewContent, {}) }),
3274
- /* @__PURE__ */ jsx(DataBodyTemplate.Tab, { id: "table", label: "Table", count: users.length, children: /* @__PURE__ */ jsx(UserTable, {}) }),
3275
- /* @__PURE__ */ jsx(DataBodyTemplate.Tab, { id: "cards", label: "Cards", count: users.length, children: /* @__PURE__ */ jsx(UserCards, {}) }),
3276
- /* @__PURE__ */ jsx(DataBodyTemplate.Tab, { id: "custom", label: "Custom", children: /* @__PURE__ */ jsx(CustomContent, {}) }),
3277
- /* @__PURE__ */ jsx(DataBodyTemplate.Tab, { id: "empty", label: "Empty", children: /* @__PURE__ */ jsxs("div", { className: "space-y-6 py-4", children: [
3278
- /* @__PURE__ */ jsx(
3279
- EmptyState,
3280
- {
3281
- icon: Users,
3282
- title: "No users yet",
3283
- description: "Add your first user to get started.",
3284
- action: { label: "Add User", onClick: () => {
3285
- } }
3286
- }
3287
- ),
3288
- /* @__PURE__ */ jsx("div", { className: "border-t" }),
2719
+ className: cn(
2720
+ "grid h-full min-h-0 grid-cols-1 overflow-hidden",
2721
+ outsideAsideSlot && "lg:grid-cols-[minmax(0,1fr)_minmax(18rem,24rem)]"
2722
+ ),
2723
+ children: [
3289
2724
  /* @__PURE__ */ jsx(
3290
- EmptyState,
2725
+ "main",
3291
2726
  {
3292
- icon: Search,
3293
- title: "No results found",
3294
- description: "Try adjusting your search or filters.",
3295
- action: { label: "Clear filters", variant: "ghost", onClick: () => {
3296
- } }
2727
+ className: cn(
2728
+ "min-h-0 overflow-auto px-(--dk-page-padding-x) py-(--dk-page-padding-y)",
2729
+ contentClassName
2730
+ ),
2731
+ children: layout[variant]
3297
2732
  }
3298
2733
  ),
3299
- /* @__PURE__ */ jsx("div", { className: "border-t" }),
3300
- /* @__PURE__ */ jsx(
3301
- EmptyState,
2734
+ outsideAsideSlot && /* @__PURE__ */ jsx("aside", { className: cn("min-h-0 border-t bg-background lg:border-l lg:border-t-0", asideClassName), children: /* @__PURE__ */ jsx(
2735
+ "div",
3302
2736
  {
3303
- icon: RefreshCw,
3304
- title: "Something went wrong",
3305
- description: "Failed to load data. Please try again.",
3306
- action: { label: "Retry", onClick: () => {
3307
- } }
2737
+ className: cn(
2738
+ "px-(--dk-page-padding-x) py-(--dk-page-padding-y)",
2739
+ stickyAside && "lg:sticky lg:top-0"
2740
+ ),
2741
+ children: outsideAsideSlot
3308
2742
  }
3309
- )
3310
- ] }) })
3311
- ]
3312
- }
3313
- );
3314
- }
3315
- function buildDataBodyTemplateCode({ themeProp, layoutClassName }) {
3316
- return [
3317
- `import { DataBodyTemplate } from '@loykin/designkit'`,
3318
- `import '@loykin/designkit/styles'`,
3319
- "",
3320
- `export function MyPage() {`,
3321
- ` return (`,
3322
- ` <DataBodyTemplate${themeProp}`,
3323
- ` className="${layoutClassName}"`,
3324
- ` title="Page Title"`,
3325
- ` >`,
3326
- ` <DataBodyTemplate.Tab id="table" label="Table">`,
3327
- ` {/* table content */}`,
3328
- ` </DataBodyTemplate.Tab>`,
3329
- ``,
3330
- ` <DataBodyTemplate.Tab id="split" label="Split">`,
3331
- ` <DataBodyTemplate.Group layout="split">`,
3332
- ` <aside>{/* list content */}</aside>`,
3333
- ` <section>{/* detail content */}</section>`,
3334
- ` </DataBodyTemplate.Group>`,
3335
- ` </DataBodyTemplate.Tab>`,
3336
- ` </DataBodyTemplate>`,
3337
- ` )`,
3338
- `}`
3339
- ].join("\n");
2743
+ ) })
2744
+ ]
2745
+ }
2746
+ ) })
2747
+ ] });
3340
2748
  }
2749
+ var DetailBodyTemplate = Object.assign(DetailBodyTemplateRoot, {
2750
+ Header: DetailBodyHeader,
2751
+ Tab: DetailBodyTab,
2752
+ Section: DetailBodySection
2753
+ });
3341
2754
  function FormWizardBodyTemplate({
3342
2755
  theme,
3343
2756
  title,
3344
2757
  topBar,
3345
2758
  variant = "plain",
3346
- steps: steps2,
2759
+ steps,
3347
2760
  activeStep,
3348
2761
  onNext,
3349
2762
  onBack,
3350
2763
  onFinish
3351
2764
  }) {
3352
- const current = steps2[activeStep];
3353
- const isLast = activeStep === steps2.length - 1;
2765
+ const current = steps[activeStep];
2766
+ const isLast = activeStep === steps.length - 1;
3354
2767
  function handleStepSubmit(e) {
3355
2768
  e.preventDefault();
3356
2769
  if (isLast) onFinish?.();
@@ -3359,7 +2772,7 @@ function FormWizardBodyTemplate({
3359
2772
  return /* @__PURE__ */ jsxs(DataPage, { className: "layout-form-wizard", style: theme, children: [
3360
2773
  topBar && /* @__PURE__ */ jsx("div", { className: "shrink-0", children: topBar }),
3361
2774
  /* @__PURE__ */ jsx(DataPage.Header, { children: /* @__PURE__ */ jsx(DataPage.TitleBlock, { title }) }),
3362
- /* @__PURE__ */ jsx("div", { className: "shrink-0 px-(--dk-page-padding-x) pb-4", children: /* @__PURE__ */ jsx("div", { className: "flex items-center", children: steps2.map((step, i) => /* @__PURE__ */ jsxs(Fragment, { children: [
2775
+ /* @__PURE__ */ jsx("div", { className: "shrink-0 px-(--dk-page-padding-x) pb-4", children: /* @__PURE__ */ jsx("div", { className: "flex items-center", children: steps.map((step, i) => /* @__PURE__ */ jsxs(Fragment, { children: [
3363
2776
  i > 0 && /* @__PURE__ */ jsx(
3364
2777
  "div",
3365
2778
  {
@@ -3423,210 +2836,13 @@ function FormWizardBodyTemplate({
3423
2836
  "Step ",
3424
2837
  activeStep + 1,
3425
2838
  " of ",
3426
- steps2.length
2839
+ steps.length
3427
2840
  ] }),
3428
2841
  /* @__PURE__ */ jsx(Button, { type: "submit", form: current?.key, size: "sm", className: "h-8 text-xs", children: isLast ? "Finish" : "Continue" })
3429
2842
  ] })
3430
2843
  ] }) })
3431
2844
  ] });
3432
2845
  }
3433
- var steps = [
3434
- {
3435
- key: "account",
3436
- title: "Your Details",
3437
- description: "Create your account credentials.",
3438
- content: /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
3439
- /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-3", children: [
3440
- /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
3441
- /* @__PURE__ */ jsx(Label, { htmlFor: "wiz-first-name", className: "text-xs", children: "First Name" }),
3442
- /* @__PURE__ */ jsx(Input, { id: "wiz-first-name", defaultValue: "Sarah", className: "h-8 text-sm" })
3443
- ] }),
3444
- /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
3445
- /* @__PURE__ */ jsx(Label, { htmlFor: "wiz-last-name", className: "text-xs", children: "Last Name" }),
3446
- /* @__PURE__ */ jsx(Input, { id: "wiz-last-name", defaultValue: "Kim", className: "h-8 text-sm" })
3447
- ] })
3448
- ] }),
3449
- /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
3450
- /* @__PURE__ */ jsx(Label, { htmlFor: "wiz-email", className: "text-xs", children: "Work Email" }),
3451
- /* @__PURE__ */ jsx(Input, { id: "wiz-email", type: "email", defaultValue: "sarah@acme.com", className: "h-8 text-sm" })
3452
- ] }),
3453
- /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
3454
- /* @__PURE__ */ jsx(Label, { htmlFor: "wiz-password", className: "text-xs", children: "Password" }),
3455
- /* @__PURE__ */ jsx(Input, { id: "wiz-password", type: "password", placeholder: "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022", className: "h-8 text-sm" }),
3456
- /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: "At least 8 characters." })
3457
- ] }),
3458
- /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
3459
- /* @__PURE__ */ jsx(Label, { htmlFor: "wiz-confirm-password", className: "text-xs", children: "Confirm Password" }),
3460
- /* @__PURE__ */ jsx(Input, { id: "wiz-confirm-password", type: "password", placeholder: "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022", className: "h-8 text-sm" })
3461
- ] })
3462
- ] })
3463
- },
3464
- {
3465
- key: "role",
3466
- title: "Your Role",
3467
- description: "Tell us about yourself so we can tailor your experience.",
3468
- content: /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
3469
- /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
3470
- /* @__PURE__ */ jsx(Label, { htmlFor: "wiz-job-title", className: "text-xs", children: "Job Title" }),
3471
- /* @__PURE__ */ jsx(Input, { id: "wiz-job-title", defaultValue: "Senior Frontend Engineer", className: "h-8 text-sm" })
3472
- ] }),
3473
- /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
3474
- /* @__PURE__ */ jsx(Label, { htmlFor: "wiz-department", className: "text-xs", children: "Department" }),
3475
- /* @__PURE__ */ jsxs(Select, { defaultValue: "engineering", children: [
3476
- /* @__PURE__ */ jsx(SelectTrigger, { className: "h-8 text-sm", children: /* @__PURE__ */ jsx(SelectValue, {}) }),
3477
- /* @__PURE__ */ jsxs(SelectContent, { children: [
3478
- /* @__PURE__ */ jsx(SelectItem, { value: "engineering", children: "Engineering" }),
3479
- /* @__PURE__ */ jsx(SelectItem, { value: "design", children: "Design" }),
3480
- /* @__PURE__ */ jsx(SelectItem, { value: "product", children: "Product" }),
3481
- /* @__PURE__ */ jsx(SelectItem, { value: "marketing", children: "Marketing" }),
3482
- /* @__PURE__ */ jsx(SelectItem, { value: "ops", children: "Operations" })
3483
- ] })
3484
- ] })
3485
- ] }),
3486
- /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
3487
- /* @__PURE__ */ jsx(Label, { htmlFor: "wiz-team-size", className: "text-xs", children: "Team Size" }),
3488
- /* @__PURE__ */ jsxs(Select, { defaultValue: "11-50", children: [
3489
- /* @__PURE__ */ jsx(SelectTrigger, { id: "wiz-team-size", className: "h-8 text-sm", children: /* @__PURE__ */ jsx(SelectValue, {}) }),
3490
- /* @__PURE__ */ jsxs(SelectContent, { children: [
3491
- /* @__PURE__ */ jsx(SelectItem, { value: "1-10", children: "1\u201310" }),
3492
- /* @__PURE__ */ jsx(SelectItem, { value: "11-50", children: "11\u201350" }),
3493
- /* @__PURE__ */ jsx(SelectItem, { value: "51-200", children: "51\u2013200" }),
3494
- /* @__PURE__ */ jsx(SelectItem, { value: "200+", children: "200+" })
3495
- ] })
3496
- ] })
3497
- ] })
3498
- ] })
3499
- },
3500
- {
3501
- key: "preferences",
3502
- title: "Preferences",
3503
- description: "Configure your defaults. You can change these anytime.",
3504
- content: /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
3505
- /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-3", children: [
3506
- /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
3507
- /* @__PURE__ */ jsx(Label, { className: "text-xs", children: "Timezone" }),
3508
- /* @__PURE__ */ jsxs(Select, { defaultValue: "asia-seoul", children: [
3509
- /* @__PURE__ */ jsx(SelectTrigger, { className: "h-8 text-sm", children: /* @__PURE__ */ jsx(SelectValue, {}) }),
3510
- /* @__PURE__ */ jsxs(SelectContent, { children: [
3511
- /* @__PURE__ */ jsx(SelectItem, { value: "asia-seoul", children: "Asia / Seoul" }),
3512
- /* @__PURE__ */ jsx(SelectItem, { value: "us-eastern", children: "US / Eastern" }),
3513
- /* @__PURE__ */ jsx(SelectItem, { value: "us-pacific", children: "US / Pacific" }),
3514
- /* @__PURE__ */ jsx(SelectItem, { value: "europe-london", children: "Europe / London" })
3515
- ] })
3516
- ] })
3517
- ] }),
3518
- /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
3519
- /* @__PURE__ */ jsx(Label, { className: "text-xs", children: "Date Format" }),
3520
- /* @__PURE__ */ jsxs(Select, { defaultValue: "ymd", children: [
3521
- /* @__PURE__ */ jsx(SelectTrigger, { className: "h-8 text-sm", children: /* @__PURE__ */ jsx(SelectValue, {}) }),
3522
- /* @__PURE__ */ jsxs(SelectContent, { children: [
3523
- /* @__PURE__ */ jsx(SelectItem, { value: "ymd", children: "YYYY-MM-DD" }),
3524
- /* @__PURE__ */ jsx(SelectItem, { value: "mdy", children: "MM/DD/YYYY" }),
3525
- /* @__PURE__ */ jsx(SelectItem, { value: "dmy", children: "DD/MM/YYYY" })
3526
- ] })
3527
- ] })
3528
- ] })
3529
- ] }),
3530
- /* @__PURE__ */ jsx("div", { className: "space-y-3 pt-1", children: [
3531
- { label: "Email notifications", desc: "Get notified of important activity.", on: true },
3532
- { label: "Weekly digest", desc: "A weekly summary email every Monday.", on: false },
3533
- { label: "Browser push", desc: "Real-time desktop notifications.", on: true }
3534
- ].map((item) => /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
3535
- /* @__PURE__ */ jsxs("div", { children: [
3536
- /* @__PURE__ */ jsx("p", { className: "text-sm font-medium", children: item.label }),
3537
- /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: item.desc })
3538
- ] }),
3539
- /* @__PURE__ */ jsx(Switch, { defaultChecked: item.on })
3540
- ] }, item.label)) })
3541
- ] })
3542
- },
3543
- {
3544
- key: "review",
3545
- title: "Review & Confirm",
3546
- description: "Check your details before creating the account.",
3547
- content: /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
3548
- /* @__PURE__ */ jsx("div", { className: "rounded-lg border divide-y", children: [
3549
- { label: "Name", value: "Sarah Kim" },
3550
- { label: "Email", value: "sarah@acme.com" },
3551
- { label: "Department", value: "Engineering" },
3552
- { label: "Timezone", value: "Asia / Seoul" }
3553
- ].map((row) => /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-4 py-2.5", children: [
3554
- /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground w-28 shrink-0", children: row.label }),
3555
- /* @__PURE__ */ jsx("span", { className: "text-sm font-medium flex-1", children: row.value }),
3556
- /* @__PURE__ */ jsx(Badge, { variant: "outline", className: "text-[10px] h-5", children: "Edit" })
3557
- ] }, row.label)) }),
3558
- /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-2.5 pt-1", children: [
3559
- /* @__PURE__ */ jsx(Checkbox, { id: "terms", className: "mt-0.5" }),
3560
- /* @__PURE__ */ jsxs(
3561
- Label,
3562
- {
3563
- htmlFor: "terms",
3564
- className: "text-xs text-muted-foreground leading-relaxed cursor-pointer",
3565
- children: [
3566
- "I agree to the",
3567
- " ",
3568
- /* @__PURE__ */ jsx("span", { className: "text-foreground underline underline-offset-2", children: "Terms of Service" }),
3569
- " ",
3570
- "and ",
3571
- /* @__PURE__ */ jsx("span", { className: "text-foreground underline underline-offset-2", children: "Privacy Policy" }),
3572
- "."
3573
- ]
3574
- }
3575
- )
3576
- ] })
3577
- ] })
3578
- }
3579
- ];
3580
- function FormWizardBodyTemplateDemo({
3581
- theme,
3582
- variant,
3583
- topBarShow,
3584
- topBarVariant,
3585
- topBarBg
3586
- }) {
3587
- const [activeStep, setActiveStep] = useState(0);
3588
- return /* @__PURE__ */ jsx(
3589
- FormWizardBodyTemplate,
3590
- {
3591
- theme,
3592
- variant,
3593
- topBar: buildTopBar({ topBarShow, topBarVariant, topBarBg, left: "Pages / Form / Wizard" }),
3594
- title: "Create Account",
3595
- steps,
3596
- activeStep,
3597
- onNext: () => setActiveStep((s) => Math.min(s + 1, steps.length - 1)),
3598
- onBack: () => setActiveStep((s) => Math.max(s - 1, 0)),
3599
- onFinish: () => setActiveStep(0)
3600
- }
3601
- );
3602
- }
3603
- function buildFormWizardBodyTemplateCode({ themeProp }) {
3604
- return [
3605
- `import { useState } from 'react'`,
3606
- `import { FormWizardBodyTemplate, type FormWizardStep } from '@loykin/designkit'`,
3607
- `import '@loykin/designkit/styles'`,
3608
- "",
3609
- `const steps: FormWizardStep[] = [`,
3610
- ` { key: 'info', title: 'Basic Info', content: <div>{/* step 1 */}</div> },`,
3611
- ` { key: 'config', title: 'Configuration', content: <div>{/* step 2 */}</div> },`,
3612
- ` { key: 'review', title: 'Review', content: <div>{/* step 3 */}</div> },`,
3613
- `]`,
3614
- "",
3615
- `export function MyPage() {`,
3616
- ` const [step, setStep] = useState(0)`,
3617
- ` return (`,
3618
- ` <FormWizardBodyTemplate${themeProp}`,
3619
- ` title="Setup Wizard"`,
3620
- ` steps={steps}`,
3621
- ` activeStep={step}`,
3622
- ` onNext={() => setStep((s) => Math.min(s + 1, steps.length - 1))}`,
3623
- ` onBack={() => setStep((s) => Math.max(s - 1, 0))}`,
3624
- ` onFinish={() => { /* handle finish */ }}`,
3625
- ` />`,
3626
- ` )`,
3627
- `}`
3628
- ].join("\n");
3629
- }
3630
2846
  var scaleRows = [
3631
2847
  { label: "Page title", className: "text-xl font-semibold", sample: "Customer Operations" },
3632
2848
  { label: "Section title", className: "text-base font-medium", sample: "Service Health" },
@@ -3715,7 +2931,7 @@ var useThemeStore = create((set) => ({
3715
2931
  density: "default",
3716
2932
  darkMode: false
3717
2933
  },
3718
- overrides: createTemplateOverrides(),
2934
+ overrides: {},
3719
2935
  activeShell: "sidebar",
3720
2936
  activeTemplate: "table",
3721
2937
  setGlobal: (patch) => set((s) => ({ global: { ...s.global, ...patch } })),
@@ -4008,1490 +3224,149 @@ function LoginBodyTemplate({
4008
3224
  }
4009
3225
  );
4010
3226
  }
4011
- var demoData = [
4012
- {
4013
- id: "1",
4014
- name: "Sarah Kim",
4015
- email: "sarah@acme.com",
4016
- role: "Admin",
4017
- status: "active",
4018
- joined: "Jan 12, 2024"
4019
- },
4020
- {
4021
- id: "2",
4022
- name: "Marcus Lee",
4023
- email: "marcus@acme.com",
4024
- role: "Editor",
4025
- status: "active",
4026
- joined: "Feb 3, 2024"
4027
- },
4028
- {
4029
- id: "3",
4030
- name: "Ji-Yeon Park",
4031
- email: "jiyeon@acme.com",
4032
- role: "Viewer",
4033
- status: "inactive",
4034
- joined: "Mar 18, 2024"
4035
- },
4036
- {
4037
- id: "4",
4038
- name: "Alex Chen",
4039
- email: "alex@acme.com",
4040
- role: "Editor",
4041
- status: "active",
4042
- joined: "Apr 7, 2024"
4043
- },
4044
- {
4045
- id: "5",
4046
- name: "Dana White",
4047
- email: "dana@acme.com",
4048
- role: "Viewer",
4049
- status: "pending",
4050
- joined: "Apr 29, 2024"
4051
- },
4052
- {
4053
- id: "6",
4054
- name: "Leo Torres",
4055
- email: "leo@acme.com",
4056
- role: "Admin",
4057
- status: "inactive",
4058
- joined: "May 1, 2024"
4059
- },
4060
- {
4061
- id: "7",
4062
- name: "Mina Seo",
4063
- email: "mina@acme.com",
4064
- role: "Editor",
4065
- status: "active",
4066
- joined: "May 2, 2024"
4067
- },
4068
- {
4069
- id: "8",
4070
- name: "Ryan Patel",
4071
- email: "ryan@acme.com",
4072
- role: "Viewer",
4073
- status: "active",
4074
- joined: "May 15, 2024"
4075
- },
4076
- {
4077
- id: "9",
4078
- name: "Yuna Choi",
4079
- email: "yuna@acme.com",
4080
- role: "Editor",
4081
- status: "pending",
4082
- joined: "Jun 3, 2024"
4083
- },
4084
- {
4085
- id: "10",
4086
- name: "Tom Fischer",
4087
- email: "tom@acme.com",
4088
- role: "Viewer",
4089
- status: "active",
4090
- joined: "Jun 20, 2024"
4091
- }
4092
- ];
4093
- var demoInfiniteData = Array.from({ length: 120 }, (_, index) => {
4094
- const source = demoData[index % demoData.length];
4095
- const id = String(index + 1);
4096
- return {
4097
- ...source,
4098
- id,
4099
- name: `${source.name} ${id}`,
4100
- email: source.email.replace("@", `+${id}@`)
4101
- };
4102
- });
4103
- var statusVariant2 = { active: "default", pending: "secondary", inactive: "outline" };
4104
- var demoColumns = [
4105
- {
4106
- id: "name",
4107
- accessorKey: "name",
4108
- header: "Name",
4109
- cell: ({ row }) => /* @__PURE__ */ jsx("span", { className: "font-medium", children: row.original.name })
4110
- },
4111
- {
4112
- id: "email",
4113
- accessorKey: "email",
4114
- header: "Email",
4115
- cell: ({ row }) => /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: row.original.email })
4116
- },
4117
- {
4118
- id: "role",
4119
- accessorKey: "role",
4120
- header: "Role",
4121
- cell: ({ row }) => /* @__PURE__ */ jsx(Badge, { variant: "outline", className: "text-xs font-normal", children: row.original.role })
4122
- },
4123
- {
4124
- id: "status",
4125
- accessorKey: "status",
4126
- header: "Status",
4127
- cell: ({ row }) => /* @__PURE__ */ jsx(Badge, { variant: statusVariant2[row.original.status], className: "text-xs capitalize", children: row.original.status })
4128
- },
4129
- {
4130
- id: "joined",
4131
- accessorKey: "joined",
4132
- header: "Joined",
4133
- cell: ({ row }) => /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: row.original.joined })
4134
- }
4135
- ];
4136
- var headerLeft2 = (table) => /* @__PURE__ */ jsx(GlobalSearch, { table, placeholder: "Search..." });
4137
- var headerRight2 = () => /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
4138
- /* @__PURE__ */ jsxs(Button, { variant: "outline", size: "sm", className: "h-8 gap-1.5 text-xs", children: [
4139
- /* @__PURE__ */ jsx(Download, { className: "h-3.5 w-3.5" }),
4140
- "Export"
4141
- ] }),
4142
- /* @__PURE__ */ jsxs(Button, { size: "sm", className: "h-8 gap-1.5 text-xs", children: [
4143
- /* @__PURE__ */ jsx(Plus, { className: "h-3.5 w-3.5" }),
4144
- "Add User"
4145
- ] })
4146
- ] });
4147
- function renderDemoCard(variant) {
4148
- return (row) => {
4149
- const user = row.original;
4150
- if (variant === "card-list") {
4151
- return /* @__PURE__ */ jsx(Card, { size: "sm", className: "rounded-lg border border-border shadow-sm ring-0", children: /* @__PURE__ */ jsxs(CardContent, { className: "flex items-center justify-between gap-4 py-2.5", children: [
4152
- /* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
4153
- /* @__PURE__ */ jsx("p", { className: "truncate text-sm font-medium", children: user.name }),
4154
- /* @__PURE__ */ jsx("p", { className: "truncate text-xs text-muted-foreground", children: user.email })
4155
- ] }),
4156
- /* @__PURE__ */ jsxs("div", { className: "flex shrink-0 items-center gap-4 text-xs", children: [
4157
- /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: user.role }),
4158
- /* @__PURE__ */ jsx(Badge, { variant: statusVariant2[user.status], className: "text-xs capitalize", children: user.status }),
4159
- /* @__PURE__ */ jsx("span", { className: "w-20 text-right text-muted-foreground", children: user.joined })
4160
- ] })
4161
- ] }) });
4162
- }
4163
- return /* @__PURE__ */ jsx(Card, { size: "sm", className: "h-full rounded-lg border border-border shadow-sm ring-0", children: /* @__PURE__ */ jsxs(CardContent, { className: "py-3", children: [
4164
- /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-3", children: [
4165
- /* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
4166
- /* @__PURE__ */ jsx("p", { className: "truncate text-sm font-medium", children: user.name }),
4167
- /* @__PURE__ */ jsx("p", { className: "truncate text-xs text-muted-foreground", children: user.email })
4168
- ] }),
4169
- /* @__PURE__ */ jsx(Badge, { variant: statusVariant2[user.status], className: "text-xs capitalize", children: user.status })
4170
- ] }),
4171
- /* @__PURE__ */ jsxs("div", { className: "mt-4 grid grid-cols-2 gap-3 text-xs", children: [
4172
- /* @__PURE__ */ jsxs("div", { children: [
4173
- /* @__PURE__ */ jsx("p", { className: "text-muted-foreground", children: "Role" }),
4174
- /* @__PURE__ */ jsx("p", { className: "mt-0.5 font-medium", children: user.role })
4175
- ] }),
4176
- /* @__PURE__ */ jsxs("div", { children: [
4177
- /* @__PURE__ */ jsx("p", { className: "text-muted-foreground", children: "Joined" }),
4178
- /* @__PURE__ */ jsx("p", { className: "mt-0.5 font-medium", children: user.joined })
4179
- ] })
4180
- ] })
4181
- ] }) });
4182
- };
4183
- }
4184
- function getDefaultLayoutClassName(variant) {
4185
- return variant === "standard" ? "layout-table" : `layout-table-${variant}`;
4186
- }
4187
- function DataGridTemplateDemo({
4188
- theme,
4189
- variant = "standard",
4190
- layoutClassName = getDefaultLayoutClassName(variant),
4191
- topBar,
4192
- title = "Users",
4193
- description,
4194
- topBarShow,
4195
- topBarVariant,
4196
- topBarBg
4197
- }) {
4198
- const resolvedTopBar = topBarShow !== void 0 || topBarVariant !== void 0 || topBarBg !== void 0 ? buildTopBar({ topBarShow, topBarVariant, topBarBg, left: "Data / Table" }) : topBar ?? /* @__PURE__ */ jsx(PageTopBar, { left: "Data / Table" });
4199
- const [visibleCount, setVisibleCount] = useState(40);
4200
- const [isFetching, setIsFetching] = useState(false);
4201
- const visibleData = demoInfiniteData.slice(0, visibleCount);
4202
- const hasNextPage = visibleCount < demoInfiniteData.length;
4203
- useEffect(() => {
4204
- setVisibleCount(40);
4205
- }, [variant]);
4206
- const fetchNextPage = () => {
4207
- if (isFetching || !hasNextPage) return;
4208
- setIsFetching(true);
4209
- window.setTimeout(() => {
4210
- setVisibleCount((count) => Math.min(count + 30, demoInfiniteData.length));
4211
- setIsFetching(false);
4212
- }, 250);
4213
- };
3227
+ function Breadcrumb({ className, ...props }) {
4214
3228
  return /* @__PURE__ */ jsx(
4215
- DataBodyTemplate,
4216
- {
4217
- theme: { "--dg-card-padding": "0px", ...theme },
4218
- className: layoutClassName,
4219
- topBar: resolvedTopBar,
4220
- title,
4221
- description,
4222
- contentClassName: variant === "infinity" ? "pb-0" : void 0,
4223
- children: /* @__PURE__ */ jsx(DataBodyTemplate.Body, { className: "[&_.dg-shell]:h-full [&_.dg-table-wrapper]:min-h-0 [&_.dg-table-wrapper]:flex-1", children: /* @__PURE__ */ jsx(
4224
- DataGridView,
4225
- {
4226
- data: variant === "infinity" ? visibleData : demoData,
4227
- columns: demoColumns,
4228
- getRowId: (row) => row.id,
4229
- variant,
4230
- enableColumnFilters: variant === "infinity" || variant === "card" || variant === "card-list",
4231
- headerLeft: headerLeft2,
4232
- headerRight: headerRight2,
4233
- pagination: { pageSize: 10 },
4234
- footer: (table) => /* @__PURE__ */ jsxs("div", { className: "flex h-9 items-center justify-between px-1 text-xs text-muted-foreground", children: [
4235
- /* @__PURE__ */ jsxs("span", { children: [
4236
- demoData.length,
4237
- " results"
4238
- ] }),
4239
- /* @__PURE__ */ jsx(DataGridPaginationCompact, { table })
4240
- ] }),
4241
- infinity: {
4242
- data: visibleData,
4243
- hasNextPage,
4244
- isFetchingNextPage: isFetching,
4245
- fetchNextPage,
4246
- tableKey: "table-infinity-template"
4247
- },
4248
- card: { renderCard: renderDemoCard(variant) }
4249
- }
4250
- ) })
4251
- }
4252
- );
4253
- }
4254
- function buildDataGridTemplateCode({
4255
- definition,
4256
- themeProp,
4257
- layoutClassName
4258
- }) {
4259
- const variant = definition.preview?.variant;
4260
- const variantProp = variant && variant !== "standard" ? `
4261
- variant="${variant}"` : "";
4262
- const cN = "className";
4263
- const cardRenderCode = definition.exportKind === "data-grid-card" ? [
4264
- "",
4265
- `function renderCard(row: { original: User }) {`,
4266
- ` const user = row.original`,
4267
- ` return (`,
4268
- ` <div ${cN}="rounded-lg border bg-card p-3 text-card-foreground">`,
4269
- ` <p ${cN}="text-sm font-medium">{user.name}</p>`,
4270
- ` <p ${cN}="text-xs text-muted-foreground">{user.email}</p>`,
4271
- ` </div>`,
4272
- ` )`,
4273
- `}`
4274
- ].join("\n") : "";
4275
- const cardProp = definition.exportKind === "data-grid-card" ? `
4276
- card={{ renderCard }}` : "";
4277
- return [
4278
- `import { DataBodyTemplate, DataGridView, PageTopBar, type DataGridColumnDef } from '@loykin/designkit'`,
4279
- `import '@loykin/designkit/styles'`,
4280
- "",
4281
- `type User = Record<string, unknown> & { id: string; name: string; email: string }`,
4282
- ``,
4283
- `const data: User[] = []`,
4284
- `const columns: DataGridColumnDef<User>[] = [`,
4285
- ` { id: 'name', accessorKey: 'name', header: 'Name' },`,
4286
- ` { id: 'email', accessorKey: 'email', header: 'Email' },`,
4287
- `]`,
4288
- cardRenderCode,
4289
- "",
4290
- `export function MyPage() {`,
4291
- ` return (`,
4292
- ` <DataBodyTemplate${themeProp}`,
4293
- ` className="${layoutClassName}"`,
4294
- ` topBar={<PageTopBar left="Data / Users" />}`,
4295
- ` title="Users"`,
4296
- ` >`,
4297
- ` <DataBodyTemplate.Body>`,
4298
- ` <DataGridView${variantProp}`,
4299
- ` data={data}`,
4300
- ` columns={columns}`,
4301
- ` getRowId={(row) => row.id}${cardProp}`,
4302
- ` tableHeight={420}`,
4303
- ` />`,
4304
- ` </DataBodyTemplate.Body>`,
4305
- ` </DataBodyTemplate>`,
4306
- ` )`,
4307
- `}`
4308
- ].filter(Boolean).join("\n");
4309
- }
4310
- function DetailBodyTemplateDemo({ theme, topBarShow, topBarVariant, topBarBg }) {
4311
- return /* @__PURE__ */ jsxs(
4312
- DataBodyTemplate,
3229
+ "nav",
4313
3230
  {
4314
- theme,
4315
- topBar: buildTopBar({ topBarShow, topBarVariant, topBarBg, left: "Users / Sarah Kim" }),
4316
- title: "Sarah Kim",
4317
- description: "sarah@acme.com",
4318
- actions: /* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
4319
- /* @__PURE__ */ jsx(Button, { variant: "outline", size: "sm", className: "h-8 text-xs", children: "Delete" }),
4320
- /* @__PURE__ */ jsx(Button, { size: "sm", className: "h-8 text-xs", children: "Edit" })
4321
- ] }),
4322
- children: [
4323
- /* @__PURE__ */ jsxs(DataBodyTemplate.Group, { layout: "inline", title: "Identity", children: [
4324
- /* @__PURE__ */ jsx(DataBodyTemplate.Field, { label: "Full name", children: "Sarah Kim" }),
4325
- /* @__PURE__ */ jsx(DataBodyTemplate.Field, { label: "Email", children: "sarah@acme.com" }),
4326
- /* @__PURE__ */ jsx(DataBodyTemplate.Field, { label: "Role", children: /* @__PURE__ */ jsx(Badge, { variant: "outline", className: "text-xs font-normal", children: "Admin" }) }),
4327
- /* @__PURE__ */ jsx(DataBodyTemplate.Field, { label: "Status", children: /* @__PURE__ */ jsx(Badge, { className: "text-xs capitalize", children: "Active" }) }),
4328
- /* @__PURE__ */ jsx(DataBodyTemplate.Field, { label: "Joined", children: "Jan 12, 2024" })
4329
- ] }),
4330
- /* @__PURE__ */ jsxs(DataBodyTemplate.Group, { layout: "inline", title: "Account", children: [
4331
- /* @__PURE__ */ jsx(DataBodyTemplate.Field, { label: "Plan", children: "Business" }),
4332
- /* @__PURE__ */ jsx(DataBodyTemplate.Field, { label: "Seats used", children: "12 / 20" }),
4333
- /* @__PURE__ */ jsx(DataBodyTemplate.Field, { label: "Billing cycle", children: "Monthly" }),
4334
- /* @__PURE__ */ jsx(DataBodyTemplate.Field, { label: "Next renewal", children: "Jun 1, 2025" })
4335
- ] }),
4336
- /* @__PURE__ */ jsx(DataBodyTemplate.Group, { layout: "inline", title: "Danger zone", danger: true, children: /* @__PURE__ */ jsx(DataBodyTemplate.Field, { label: "Deactivate account", children: /* @__PURE__ */ jsx(
4337
- Button,
4338
- {
4339
- variant: "ghost",
4340
- size: "sm",
4341
- className: "h-7 text-xs text-destructive hover:text-destructive",
4342
- children: "Deactivate"
4343
- }
4344
- ) }) })
4345
- ]
3231
+ "aria-label": "breadcrumb",
3232
+ "data-slot": "breadcrumb",
3233
+ className: cn(className),
3234
+ ...props
4346
3235
  }
4347
3236
  );
4348
3237
  }
4349
- function buildDetailBodyTemplateCode({ themeProp, layoutClassName }) {
4350
- return [
4351
- `import { DataBodyTemplate } from '@loykin/designkit'`,
4352
- `import '@loykin/designkit/styles'`,
4353
- "",
4354
- `export function MyPage() {`,
4355
- ` return (`,
4356
- ` <DataBodyTemplate${themeProp}`,
4357
- ` className="${layoutClassName}"`,
4358
- ` breadcrumb="Users / Detail"`,
4359
- ` title="Sarah Kim"`,
4360
- ` actions={<button>Edit</button>}`,
4361
- ` >`,
4362
- ` <DataBodyTemplate.Group layout="inline" title="Identity">`,
4363
- ` <DataBodyTemplate.Field label="Name">Sarah Kim</DataBodyTemplate.Field>`,
4364
- ` <DataBodyTemplate.Field label="Email">sarah@acme.com</DataBodyTemplate.Field>`,
4365
- ` </DataBodyTemplate.Group>`,
4366
- ` </DataBodyTemplate>`,
4367
- ` )`,
4368
- `}`
4369
- ].join("\n");
4370
- }
4371
- var users2 = [
4372
- { id: "1", name: "Sarah Kim", email: "sarah@acme.com", role: "Admin", status: "active" },
4373
- { id: "2", name: "Marcus Lee", email: "marcus@acme.com", role: "Editor", status: "active" },
4374
- { id: "3", name: "Ji-Yeon Park", email: "jiyeon@acme.com", role: "Viewer", status: "inactive" },
4375
- { id: "4", name: "Alex Chen", email: "alex@acme.com", role: "Editor", status: "pending" }
4376
- ];
4377
- var statusVariant3 = { active: "default", pending: "secondary", inactive: "outline" };
4378
- function SplitBodyTemplateDemo({ theme, topBarShow, topBarVariant, topBarBg }) {
4379
- const [active, setActive] = useState(users2[0]);
3238
+ function BreadcrumbList({ className, ...props }) {
4380
3239
  return /* @__PURE__ */ jsx(
4381
- DataBodyTemplate,
4382
- {
4383
- theme,
4384
- topBar: buildTopBar({ topBarShow, topBarVariant, topBarBg, left: "Users" }),
4385
- title: "Users",
4386
- actions: /* @__PURE__ */ jsx(Button, { size: "sm", className: "h-8 text-xs", children: "Add User" }),
4387
- children: /* @__PURE__ */ jsxs(DataBodyTemplate.Group, { layout: "split", children: [
4388
- /* @__PURE__ */ jsx("div", { className: "space-y-0.5 p-2", children: users2.map((u) => /* @__PURE__ */ jsxs(
4389
- "button",
4390
- {
4391
- type: "button",
4392
- onClick: () => setActive(u),
4393
- className: [
4394
- "block w-full rounded-lg px-3 py-2 text-left transition-colors",
4395
- u.id === active.id ? "bg-accent text-accent-foreground" : "hover:bg-muted"
4396
- ].join(" "),
4397
- children: [
4398
- /* @__PURE__ */ jsx("span", { className: "block truncate text-sm font-medium", children: u.name }),
4399
- /* @__PURE__ */ jsx("span", { className: "block truncate text-xs text-muted-foreground", children: u.email })
4400
- ]
4401
- },
4402
- u.id
4403
- )) }),
4404
- /* @__PURE__ */ jsxs("div", { className: "space-y-4 p-(--dk-panel-gap)", children: [
4405
- /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-3", children: [
4406
- /* @__PURE__ */ jsxs("div", { children: [
4407
- /* @__PURE__ */ jsx("h2", { className: "text-base font-semibold", children: active.name }),
4408
- /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: active.email })
4409
- ] }),
4410
- /* @__PURE__ */ jsx(Badge, { variant: statusVariant3[active.status], className: "text-xs capitalize", children: active.status })
4411
- ] }),
4412
- /* @__PURE__ */ jsxs("div", { className: "grid gap-3 sm:grid-cols-2", children: [
4413
- /* @__PURE__ */ jsxs("div", { className: "rounded-lg border p-3", children: [
4414
- /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: "Role" }),
4415
- /* @__PURE__ */ jsx("p", { className: "mt-1 text-sm font-medium", children: active.role })
4416
- ] }),
4417
- /* @__PURE__ */ jsxs("div", { className: "rounded-lg border p-3", children: [
4418
- /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: "Status" }),
4419
- /* @__PURE__ */ jsx("p", { className: "mt-1 text-sm font-medium capitalize", children: active.status })
4420
- ] })
4421
- ] })
4422
- ] })
4423
- ] })
4424
- }
4425
- );
4426
- }
4427
- function buildSplitBodyTemplateCode({ themeProp, layoutClassName }) {
4428
- return [
4429
- `import { DataBodyTemplate } from '@loykin/designkit'`,
4430
- `import '@loykin/designkit/styles'`,
4431
- "",
4432
- `export function MyPage() {`,
4433
- ` return (`,
4434
- ` <DataBodyTemplate${themeProp}`,
4435
- ` className="${layoutClassName}"`,
4436
- ` title="Users"`,
4437
- ` >`,
4438
- ` <DataBodyTemplate.Group layout="split">`,
4439
- ` <aside>{/* list */}</aside>`,
4440
- ` <section>{/* detail */}</section>`,
4441
- ` </DataBodyTemplate.Group>`,
4442
- ` </DataBodyTemplate>`,
4443
- ` )`,
4444
- `}`
4445
- ].join("\n");
4446
- }
4447
- var issues = [
4448
- {
4449
- id: "INC-001",
4450
- title: "API gateway returning 502 on /auth endpoints",
4451
- status: "open",
4452
- priority: "critical",
4453
- assignee: "Sarah K.",
4454
- created: "2h ago"
4455
- },
4456
- {
4457
- id: "INC-002",
4458
- title: "Memory leak in data-processor worker threads",
4459
- status: "in-progress",
4460
- priority: "high",
4461
- assignee: "Marcus L.",
4462
- created: "5h ago"
4463
- },
4464
- {
4465
- id: "INC-003",
4466
- title: "Dashboard charts not rendering in Safari 17",
4467
- status: "open",
4468
- priority: "medium",
4469
- assignee: "Ji-Yeon P.",
4470
- created: "1d ago"
4471
- },
4472
- {
4473
- id: "INC-004",
4474
- title: "Slow query on users table (>3s)",
4475
- status: "resolved",
4476
- priority: "high",
4477
- assignee: "Alex C.",
4478
- created: "2d ago"
4479
- },
4480
- {
4481
- id: "INC-005",
4482
- title: "Email notifications not sent for new signups",
4483
- status: "in-progress",
4484
- priority: "medium",
4485
- assignee: "Dana W.",
4486
- created: "3d ago"
4487
- },
4488
- {
4489
- id: "INC-006",
4490
- title: "CORS error on POST /api/v2/upload from mobile",
4491
- status: "open",
4492
- priority: "high",
4493
- assignee: "Leo T.",
4494
- created: "4d ago"
4495
- },
4496
- {
4497
- id: "INC-007",
4498
- title: "Cron expression parsing failure on scheduler",
4499
- status: "closed",
4500
- priority: "low",
4501
- assignee: "Mina S.",
4502
- created: "1w ago"
4503
- }
4504
- ];
4505
- var statusIcon = {
4506
- open: /* @__PURE__ */ jsx(AlertCircle, { className: "h-3.5 w-3.5 text-destructive" }),
4507
- "in-progress": /* @__PURE__ */ jsx(Clock, { className: "h-3.5 w-3.5 text-yellow-500" }),
4508
- resolved: /* @__PURE__ */ jsx(CheckCircle2, { className: "h-3.5 w-3.5 text-primary" }),
4509
- closed: /* @__PURE__ */ jsx(XCircle, { className: "h-3.5 w-3.5 text-muted-foreground" })
4510
- };
4511
- var priorityVariant = {
4512
- critical: "destructive",
4513
- high: "default",
4514
- medium: "secondary",
4515
- low: "outline"
4516
- };
4517
- function IssueTable({ rows }) {
4518
- return /* @__PURE__ */ jsxs(Table, { children: [
4519
- /* @__PURE__ */ jsx(TableHeader, { children: /* @__PURE__ */ jsxs(TableRow, { children: [
4520
- /* @__PURE__ */ jsx(TableHead, { className: "w-24", children: "ID" }),
4521
- /* @__PURE__ */ jsx(TableHead, { children: "Title" }),
4522
- /* @__PURE__ */ jsx(TableHead, { className: "w-24", children: "Priority" }),
4523
- /* @__PURE__ */ jsx(TableHead, { className: "w-28", children: "Assignee" }),
4524
- /* @__PURE__ */ jsx(TableHead, { className: "w-24", children: "Created" }),
4525
- /* @__PURE__ */ jsx(TableHead, { className: "w-16" })
4526
- ] }) }),
4527
- /* @__PURE__ */ jsx(TableBody, { children: rows.map((issue) => /* @__PURE__ */ jsxs(TableRow, { className: "cursor-pointer", children: [
4528
- /* @__PURE__ */ jsx(TableCell, { className: "font-mono text-xs text-muted-foreground", children: issue.id }),
4529
- /* @__PURE__ */ jsx(TableCell, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
4530
- statusIcon[issue.status],
4531
- /* @__PURE__ */ jsx("span", { className: "text-sm", children: issue.title })
4532
- ] }) }),
4533
- /* @__PURE__ */ jsx(TableCell, { children: /* @__PURE__ */ jsx(Badge, { variant: priorityVariant[issue.priority], className: "text-xs capitalize", children: issue.priority }) }),
4534
- /* @__PURE__ */ jsx(TableCell, { className: "text-xs text-muted-foreground", children: issue.assignee }),
4535
- /* @__PURE__ */ jsx(TableCell, { className: "text-xs text-muted-foreground", children: issue.created }),
4536
- /* @__PURE__ */ jsx(TableCell, { children: /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", className: "h-7 text-xs", children: "View" }) })
4537
- ] }, issue.id)) })
4538
- ] });
4539
- }
4540
- var counts = {
4541
- open: issues.filter((i) => i.status === "open").length,
4542
- "in-progress": issues.filter((i) => i.status === "in-progress").length,
4543
- resolved: issues.filter((i) => i.status === "resolved").length,
4544
- closed: issues.filter((i) => i.status === "closed").length
4545
- };
4546
- function TabbedBodyTemplateDemo({ theme, topBarShow, topBarVariant, topBarBg }) {
4547
- return /* @__PURE__ */ jsxs(
4548
- DataBodyTemplate,
4549
- {
4550
- theme,
4551
- topBar: buildTopBar({ topBarShow, topBarVariant, topBarBg, left: "Pages / Tabbed" }),
4552
- title: "Incidents",
4553
- description: "Incident queue grouped by status",
4554
- toolbarLeft: /* @__PURE__ */ jsxs("div", { className: "relative", children: [
4555
- /* @__PURE__ */ jsx(Search, { className: "absolute left-2.5 top-1/2 -translate-y-1/2 h-3.5 w-3.5 text-muted-foreground" }),
4556
- /* @__PURE__ */ jsx(Input, { placeholder: "Search\u2026", className: "pl-8 h-8 w-52 text-xs" })
4557
- ] }),
4558
- toolbarRight: /* @__PURE__ */ jsxs(Button, { size: "sm", className: "h-8 gap-1.5 text-xs", children: [
4559
- /* @__PURE__ */ jsx(Plus, { className: "h-3.5 w-3.5" }),
4560
- "New Incident"
4561
- ] }),
4562
- children: [
4563
- /* @__PURE__ */ jsx(DataBodyTemplate.Summary, { children: /* @__PURE__ */ jsx("div", { className: "grid grid-cols-4 gap-(--dk-panel-gap)", children: [
4564
- { label: "Open", count: counts.open, Icon: AlertCircle, cls: "text-destructive" },
4565
- {
4566
- label: "In Progress",
4567
- count: counts["in-progress"],
4568
- Icon: Clock,
4569
- cls: "text-yellow-500"
4570
- },
4571
- {
4572
- label: "Resolved",
4573
- count: counts.resolved,
4574
- Icon: CheckCircle2,
4575
- cls: "text-primary"
4576
- },
4577
- {
4578
- label: "Closed",
4579
- count: counts.closed,
4580
- Icon: XCircle,
4581
- cls: "text-muted-foreground"
4582
- }
4583
- ].map(({ label, count, Icon, cls }) => /* @__PURE__ */ jsx(Card, { children: /* @__PURE__ */ jsxs(CardContent, { className: "flex items-center gap-[calc(var(--dk-panel-gap)*0.75)] p-[calc(var(--dk-panel-gap)*0.75)]", children: [
4584
- /* @__PURE__ */ jsx(Icon, { className: `h-5 w-5 ${cls}` }),
4585
- /* @__PURE__ */ jsxs("div", { children: [
4586
- /* @__PURE__ */ jsx("p", { className: "text-xl font-bold tabular-nums", children: count }),
4587
- /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: label })
4588
- ] })
4589
- ] }) }, label)) }) }),
4590
- /* @__PURE__ */ jsx(DataBodyTemplate.Tab, { id: "all", label: "All", count: issues.length, children: /* @__PURE__ */ jsx(IssueTable, { rows: issues }) }),
4591
- /* @__PURE__ */ jsx(DataBodyTemplate.Tab, { id: "open", label: "Open", count: counts.open, children: /* @__PURE__ */ jsx(IssueTable, { rows: issues.filter((i) => i.status === "open") }) }),
4592
- /* @__PURE__ */ jsx(DataBodyTemplate.Tab, { id: "in-progress", label: "In Progress", count: counts["in-progress"], children: /* @__PURE__ */ jsx(IssueTable, { rows: issues.filter((i) => i.status === "in-progress") }) }),
4593
- /* @__PURE__ */ jsx(DataBodyTemplate.Tab, { id: "resolved", label: "Resolved", count: counts.resolved, children: /* @__PURE__ */ jsx(IssueTable, { rows: issues.filter((i) => i.status === "resolved") }) })
4594
- ]
4595
- }
4596
- );
4597
- }
4598
- function buildTabbedBodyTemplateCode({ themeProp, layoutClassName }) {
4599
- return [
4600
- `import { DataBodyTemplate } from '@loykin/designkit'`,
4601
- `import '@loykin/designkit/styles'`,
4602
- "",
4603
- `export function MyPage() {`,
4604
- ` return (`,
4605
- ` <DataBodyTemplate${themeProp}`,
4606
- ` className="${layoutClassName}"`,
4607
- ` title="Incidents"`,
4608
- ` >`,
4609
- ` <DataBodyTemplate.Summary>`,
4610
- ` {/* summary content */}`,
4611
- ` </DataBodyTemplate.Summary>`,
4612
- ``,
4613
- ` <DataBodyTemplate.Tab id="all" label="All">`,
4614
- ` {/* tab content */}`,
4615
- ` </DataBodyTemplate.Tab>`,
4616
- ` </DataBodyTemplate>`,
4617
- ` )`,
4618
- `}`
4619
- ].join("\n");
4620
- }
4621
- function FormBodyTemplateDemo({ theme, topBarShow, topBarVariant, topBarBg }) {
4622
- return /* @__PURE__ */ jsxs(
4623
- DataBodyTemplate,
4624
- {
4625
- theme,
4626
- topBar: buildTopBar({ topBarShow, topBarVariant, topBarBg, left: "Pages / Form" }),
4627
- title: "Account Settings",
4628
- description: "Manage your account preferences and security.",
4629
- children: [
4630
- /* @__PURE__ */ jsx(
4631
- DataBodyTemplate.Group,
4632
- {
4633
- layout: "horizontal",
4634
- title: "Profile",
4635
- description: "Your public-facing name and contact info.",
4636
- children: /* @__PURE__ */ jsxs("form", { onSubmit: (e) => e.preventDefault(), className: "space-y-4", children: [
4637
- /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-4", children: [
4638
- /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
4639
- /* @__PURE__ */ jsx(Label, { htmlFor: "first-name", className: "text-xs", children: "First Name" }),
4640
- /* @__PURE__ */ jsx(Input, { id: "first-name", defaultValue: "Sarah", className: "h-8 text-sm" })
4641
- ] }),
4642
- /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
4643
- /* @__PURE__ */ jsx(Label, { htmlFor: "last-name", className: "text-xs", children: "Last Name" }),
4644
- /* @__PURE__ */ jsx(Input, { id: "last-name", defaultValue: "Kim", className: "h-8 text-sm" })
4645
- ] })
4646
- ] }),
4647
- /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
4648
- /* @__PURE__ */ jsx(Label, { htmlFor: "profile-email", className: "text-xs", children: "Email" }),
4649
- /* @__PURE__ */ jsx(Input, { id: "profile-email", type: "email", defaultValue: "sarah@acme.com", className: "h-8 text-sm" })
4650
- ] }),
4651
- /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
4652
- /* @__PURE__ */ jsx(Label, { htmlFor: "profile-role", className: "text-xs", children: "Role" }),
4653
- /* @__PURE__ */ jsxs(Select, { defaultValue: "admin", children: [
4654
- /* @__PURE__ */ jsx(SelectTrigger, { id: "profile-role", className: "h-8 text-sm", children: /* @__PURE__ */ jsx(SelectValue, {}) }),
4655
- /* @__PURE__ */ jsxs(SelectContent, { children: [
4656
- /* @__PURE__ */ jsx(SelectItem, { value: "admin", children: "Admin" }),
4657
- /* @__PURE__ */ jsx(SelectItem, { value: "editor", children: "Editor" }),
4658
- /* @__PURE__ */ jsx(SelectItem, { value: "viewer", children: "Viewer" })
4659
- ] })
4660
- ] })
4661
- ] }),
4662
- /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
4663
- /* @__PURE__ */ jsx(Label, { htmlFor: "profile-bio", className: "text-xs", children: "Bio" }),
4664
- /* @__PURE__ */ jsx(
4665
- "textarea",
4666
- {
4667
- id: "profile-bio",
4668
- className: "w-full h-20 rounded-(--radius) border border-input bg-background px-3 py-2 text-sm resize-none focus:outline-none focus:ring-2 focus:ring-ring",
4669
- defaultValue: "Frontend engineer focused on design systems."
4670
- }
4671
- )
4672
- ] }),
4673
- /* @__PURE__ */ jsx("div", { className: "flex justify-end", children: /* @__PURE__ */ jsx(Button, { type: "submit", size: "sm", className: "h-8 text-xs", children: "Save Profile" }) })
4674
- ] })
4675
- }
4676
- ),
4677
- /* @__PURE__ */ jsx(
4678
- DataBodyTemplate.Group,
4679
- {
4680
- layout: "horizontal",
4681
- title: "Notifications",
4682
- description: "Choose when and how you get notified.",
4683
- children: /* @__PURE__ */ jsx("div", { className: "divide-y", children: [
4684
- { label: "Comments on your posts", sub: "When someone replies to a thread", on: true },
4685
- { label: "Mentions", sub: "When someone @mentions you", on: true },
4686
- { label: "Weekly digest", sub: "A weekly summary of activity", on: false },
4687
- { label: "Security alerts", sub: "Login from new device", on: true },
4688
- { label: "Product updates", sub: "New features and improvements", on: false }
4689
- ].map((item) => /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between py-3", children: [
4690
- /* @__PURE__ */ jsxs("div", { children: [
4691
- /* @__PURE__ */ jsx("p", { className: "text-sm font-medium", children: item.label }),
4692
- /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: item.sub })
4693
- ] }),
4694
- /* @__PURE__ */ jsx(Switch, { defaultChecked: item.on })
4695
- ] }, item.label)) })
4696
- }
4697
- ),
4698
- /* @__PURE__ */ jsx(
4699
- DataBodyTemplate.Group,
4700
- {
4701
- layout: "horizontal",
4702
- title: "Security",
4703
- description: "Password and authentication settings.",
4704
- children: /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
4705
- /* @__PURE__ */ jsxs("form", { onSubmit: (e) => e.preventDefault(), className: "space-y-4", children: [
4706
- /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
4707
- /* @__PURE__ */ jsx(Label, { htmlFor: "current-password", className: "text-xs", children: "Current Password" }),
4708
- /* @__PURE__ */ jsx(Input, { id: "current-password", type: "password", placeholder: "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022", className: "h-8 text-sm" })
4709
- ] }),
4710
- /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-4", children: [
4711
- /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
4712
- /* @__PURE__ */ jsx(Label, { htmlFor: "new-password", className: "text-xs", children: "New Password" }),
4713
- /* @__PURE__ */ jsx(Input, { id: "new-password", type: "password", placeholder: "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022", className: "h-8 text-sm" })
4714
- ] }),
4715
- /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
4716
- /* @__PURE__ */ jsx(Label, { htmlFor: "confirm-password", className: "text-xs", children: "Confirm" }),
4717
- /* @__PURE__ */ jsx(Input, { id: "confirm-password", type: "password", placeholder: "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022", className: "h-8 text-sm" })
4718
- ] })
4719
- ] }),
4720
- /* @__PURE__ */ jsx("div", { className: "flex justify-end", children: /* @__PURE__ */ jsx(Button, { type: "submit", size: "sm", className: "h-8 text-xs", children: "Update Password" }) })
4721
- ] }),
4722
- /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between p-3 rounded-(--radius) border", children: [
4723
- /* @__PURE__ */ jsxs("div", { children: [
4724
- /* @__PURE__ */ jsx("p", { className: "text-sm font-medium", children: "Two-Factor Authentication" }),
4725
- /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: "Require OTP on every login" })
4726
- ] }),
4727
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
4728
- /* @__PURE__ */ jsx(Badge, { variant: "outline", className: "text-xs", children: "Disabled" }),
4729
- /* @__PURE__ */ jsx(Button, { type: "button", size: "sm", className: "h-8 text-xs", children: "Enable" })
4730
- ] })
4731
- ] })
4732
- ] })
4733
- }
4734
- ),
4735
- /* @__PURE__ */ jsx(
4736
- DataBodyTemplate.Group,
4737
- {
4738
- layout: "horizontal",
4739
- title: "Danger Zone",
4740
- description: "Irreversible actions. Proceed with caution.",
4741
- danger: true,
4742
- children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between p-3 rounded-(--radius) border border-destructive/40 bg-destructive/5", children: [
4743
- /* @__PURE__ */ jsxs("div", { children: [
4744
- /* @__PURE__ */ jsx("p", { className: "text-sm font-medium", children: "Delete Account" }),
4745
- /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: "Permanently delete your account and all data." })
4746
- ] }),
4747
- /* @__PURE__ */ jsx(Button, { type: "button", variant: "destructive", size: "sm", className: "h-8 text-xs", children: "Delete Account" })
4748
- ] })
4749
- }
4750
- )
4751
- ]
4752
- }
4753
- );
4754
- }
4755
- function buildFormBodyTemplateCode({ themeProp, layoutClassName }) {
4756
- return [
4757
- `import { DataBodyTemplate } from '@loykin/designkit'`,
4758
- `import '@loykin/designkit/styles'`,
4759
- "",
4760
- `export function MyPage() {`,
4761
- ` return (`,
4762
- ` <DataBodyTemplate${themeProp}`,
4763
- ` className="${layoutClassName}"`,
4764
- ` title="Account Settings"`,
4765
- ` >`,
4766
- ` <DataBodyTemplate.Group layout="horizontal" title="Profile">`,
4767
- ` <form onSubmit={handleSubmit}>`,
4768
- ` {/* form fields */}`,
4769
- ` <button type="submit">Save Profile</button>`,
4770
- ` </form>`,
4771
- ` </DataBodyTemplate.Group>`,
4772
- ` </DataBodyTemplate>`,
4773
- ` )`,
4774
- `}`
4775
- ].join("\n");
4776
- }
4777
- function FormStackedBodyTemplateDemo({ theme, topBarShow, topBarVariant, topBarBg }) {
4778
- return /* @__PURE__ */ jsxs(
4779
- DataBodyTemplate,
3240
+ "ol",
4780
3241
  {
4781
- theme,
4782
- topBar: buildTopBar({ topBarShow, topBarVariant, topBarBg, left: "Pages / Form / Stacked" }),
4783
- title: "Settings",
4784
- description: "Manage your account and preferences.",
4785
- children: [
4786
- /* @__PURE__ */ jsx(
4787
- DataBodyTemplate.Group,
4788
- {
4789
- layout: "stacked",
4790
- title: "Profile",
4791
- description: "How you appear to others on the platform.",
4792
- children: /* @__PURE__ */ jsxs("form", { onSubmit: (e) => e.preventDefault(), className: "space-y-3", children: [
4793
- /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
4794
- /* @__PURE__ */ jsx(Label, { htmlFor: "display-name", className: "text-xs", children: "Display Name" }),
4795
- /* @__PURE__ */ jsx(Input, { id: "display-name", defaultValue: "Sarah Kim", className: "h-8 text-sm" })
4796
- ] }),
4797
- /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
4798
- /* @__PURE__ */ jsx(Label, { htmlFor: "stacked-email", className: "text-xs", children: "Email" }),
4799
- /* @__PURE__ */ jsx(Input, { id: "stacked-email", type: "email", defaultValue: "sarah@acme.com", className: "h-8 text-sm", disabled: true }),
4800
- /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: "Contact support to change your email address." })
4801
- ] }),
4802
- /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
4803
- /* @__PURE__ */ jsx(Label, { htmlFor: "stacked-bio", className: "text-xs", children: "Bio" }),
4804
- /* @__PURE__ */ jsx(
4805
- "textarea",
4806
- {
4807
- id: "stacked-bio",
4808
- className: "w-full h-20 resize-none rounded-[var(--radius)] border border-input bg-background px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-ring",
4809
- defaultValue: "Frontend engineer focused on design systems."
4810
- }
4811
- )
4812
- ] }),
4813
- /* @__PURE__ */ jsx("div", { className: "flex justify-end", children: /* @__PURE__ */ jsx(Button, { type: "submit", size: "sm", className: "h-8 text-xs", children: "Save Profile" }) })
4814
- ] })
4815
- }
4816
- ),
4817
- /* @__PURE__ */ jsx(
4818
- DataBodyTemplate.Group,
4819
- {
4820
- layout: "stacked",
4821
- title: "Appearance",
4822
- description: "Customize how the interface looks for you.",
4823
- children: /* @__PURE__ */ jsxs("form", { onSubmit: (e) => e.preventDefault(), className: "space-y-3", children: [
4824
- /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
4825
- /* @__PURE__ */ jsx(Label, { htmlFor: "theme-select", className: "text-xs", children: "Theme" }),
4826
- /* @__PURE__ */ jsxs(Select, { defaultValue: "system", children: [
4827
- /* @__PURE__ */ jsx(SelectTrigger, { id: "theme-select", className: "h-8 text-sm w-44", children: /* @__PURE__ */ jsx(SelectValue, {}) }),
4828
- /* @__PURE__ */ jsxs(SelectContent, { children: [
4829
- /* @__PURE__ */ jsx(SelectItem, { value: "system", children: "System" }),
4830
- /* @__PURE__ */ jsx(SelectItem, { value: "light", children: "Light" }),
4831
- /* @__PURE__ */ jsx(SelectItem, { value: "dark", children: "Dark" })
4832
- ] })
4833
- ] })
4834
- ] }),
4835
- /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
4836
- /* @__PURE__ */ jsx(Label, { htmlFor: "language-select", className: "text-xs", children: "Language" }),
4837
- /* @__PURE__ */ jsxs(Select, { defaultValue: "en", children: [
4838
- /* @__PURE__ */ jsx(SelectTrigger, { id: "language-select", className: "h-8 text-sm w-44", children: /* @__PURE__ */ jsx(SelectValue, {}) }),
4839
- /* @__PURE__ */ jsxs(SelectContent, { children: [
4840
- /* @__PURE__ */ jsx(SelectItem, { value: "en", children: "English" }),
4841
- /* @__PURE__ */ jsx(SelectItem, { value: "ko", children: "\uD55C\uAD6D\uC5B4" }),
4842
- /* @__PURE__ */ jsx(SelectItem, { value: "ja", children: "\u65E5\u672C\u8A9E" })
4843
- ] })
4844
- ] })
4845
- ] }),
4846
- /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
4847
- /* @__PURE__ */ jsxs("div", { children: [
4848
- /* @__PURE__ */ jsx("p", { className: "text-sm font-medium", children: "Compact mode" }),
4849
- /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: "Reduce spacing across the interface." })
4850
- ] }),
4851
- /* @__PURE__ */ jsx(Switch, {})
4852
- ] }),
4853
- /* @__PURE__ */ jsx("div", { className: "flex justify-end", children: /* @__PURE__ */ jsx(Button, { type: "submit", size: "sm", className: "h-8 text-xs", children: "Save Appearance" }) })
4854
- ] })
4855
- }
4856
- ),
4857
- /* @__PURE__ */ jsx(
4858
- DataBodyTemplate.Group,
4859
- {
4860
- layout: "stacked",
4861
- title: "Privacy & Data",
4862
- description: "Manage how your data is collected and used.",
4863
- children: /* @__PURE__ */ jsx("div", { className: "space-y-4", children: [
4864
- { label: "Usage analytics", desc: "Share anonymous usage data to improve the product.", on: true },
4865
- { label: "Crash reports", desc: "Automatically send crash logs to our team.", on: true },
4866
- { label: "Marketing emails", desc: "Receive updates on new features and promotions.", on: false }
4867
- ].map((item) => /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
4868
- /* @__PURE__ */ jsxs("div", { children: [
4869
- /* @__PURE__ */ jsx("p", { className: "text-sm font-medium", children: item.label }),
4870
- /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: item.desc })
4871
- ] }),
4872
- /* @__PURE__ */ jsx(Switch, { defaultChecked: item.on })
4873
- ] }, item.label)) })
4874
- }
4875
- ),
4876
- /* @__PURE__ */ jsx(
4877
- DataBodyTemplate.Group,
4878
- {
4879
- layout: "stacked",
4880
- title: "Danger Zone",
4881
- description: "Irreversible actions. Proceed with caution.",
4882
- danger: true,
4883
- children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between rounded-[var(--radius)] border border-destructive/40 bg-destructive/5 px-4 py-3", children: [
4884
- /* @__PURE__ */ jsxs("div", { children: [
4885
- /* @__PURE__ */ jsx("p", { className: "text-sm font-medium", children: "Delete Account" }),
4886
- /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: "Permanently remove all your data." })
4887
- ] }),
4888
- /* @__PURE__ */ jsx(Button, { type: "button", variant: "destructive", size: "sm", className: "ml-4 h-8 shrink-0 text-xs", children: "Delete" })
4889
- ] })
4890
- }
4891
- )
4892
- ]
3242
+ "data-slot": "breadcrumb-list",
3243
+ className: cn(
3244
+ "flex flex-wrap items-center gap-1.5 text-sm wrap-break-word text-muted-foreground",
3245
+ className
3246
+ ),
3247
+ ...props
4893
3248
  }
4894
3249
  );
4895
3250
  }
4896
- function buildFormStackedBodyTemplateCode({
4897
- themeProp,
4898
- layoutClassName
4899
- }) {
4900
- return [
4901
- `import { DataBodyTemplate } from '@loykin/designkit'`,
4902
- `import '@loykin/designkit/styles'`,
4903
- "",
4904
- `export function MyPage() {`,
4905
- ` return (`,
4906
- ` <DataBodyTemplate${themeProp}`,
4907
- ` className="${layoutClassName}"`,
4908
- ` title="Settings"`,
4909
- ` >`,
4910
- ` <DataBodyTemplate.Group layout="stacked" title="Profile">`,
4911
- ` <form onSubmit={handleSubmit}>`,
4912
- ` {/* form fields */}`,
4913
- ` <button type="submit">Save Profile</button>`,
4914
- ` </form>`,
4915
- ` </DataBodyTemplate.Group>`,
4916
- ` </DataBodyTemplate>`,
4917
- ` )`,
4918
- `}`
4919
- ].join("\n");
4920
- }
4921
- function FormInlineBodyTemplateDemo({ theme, topBarShow, topBarVariant, topBarBg }) {
3251
+ function BreadcrumbItem({ className, ...props }) {
4922
3252
  return /* @__PURE__ */ jsx(
4923
- DataBodyTemplate,
3253
+ "li",
4924
3254
  {
4925
- theme,
4926
- topBar: buildTopBar({ topBarShow, topBarVariant, topBarBg, left: "Pages / Form / Inline" }),
4927
- title: "Edit User",
4928
- description: "Update user profile and access settings.",
4929
- children: /* @__PURE__ */ jsxs("form", { onSubmit: (e) => e.preventDefault(), className: "contents", children: [
4930
- /* @__PURE__ */ jsxs(DataBodyTemplate.Group, { layout: "inline", title: "Identity", children: [
4931
- /* @__PURE__ */ jsx(DataBodyTemplate.Row, { label: "Full Name", required: true, children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-2", children: [
4932
- /* @__PURE__ */ jsx(Input, { defaultValue: "Sarah", className: "h-8 text-sm", placeholder: "First" }),
4933
- /* @__PURE__ */ jsx(Input, { defaultValue: "Kim", className: "h-8 text-sm", placeholder: "Last" })
4934
- ] }) }),
4935
- /* @__PURE__ */ jsx(
4936
- DataBodyTemplate.Row,
4937
- {
4938
- label: "Email",
4939
- description: "Used for login and notifications.",
4940
- required: true,
4941
- children: /* @__PURE__ */ jsx(Input, { type: "email", defaultValue: "sarah@acme.com", className: "h-8 text-sm" })
4942
- }
4943
- ),
4944
- /* @__PURE__ */ jsx(DataBodyTemplate.Row, { label: "Username", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
4945
- /* @__PURE__ */ jsx(Input, { defaultValue: "sarah.kim", className: "h-8 text-sm" }),
4946
- /* @__PURE__ */ jsx(Badge, { variant: "outline", className: "text-[10px] h-6 shrink-0", children: "Available" })
4947
- ] }) }),
4948
- /* @__PURE__ */ jsx(DataBodyTemplate.Row, { label: "Phone", children: /* @__PURE__ */ jsx(Input, { type: "tel", defaultValue: "+82 10-1234-5678", className: "h-8 text-sm" }) })
4949
- ] }),
4950
- /* @__PURE__ */ jsxs(DataBodyTemplate.Group, { layout: "inline", title: "Role & Access", children: [
4951
- /* @__PURE__ */ jsx(DataBodyTemplate.Row, { label: "Role", required: true, children: /* @__PURE__ */ jsxs(Select, { defaultValue: "admin", children: [
4952
- /* @__PURE__ */ jsx(SelectTrigger, { className: "h-8 text-sm", children: /* @__PURE__ */ jsx(SelectValue, {}) }),
4953
- /* @__PURE__ */ jsxs(SelectContent, { children: [
4954
- /* @__PURE__ */ jsx(SelectItem, { value: "admin", children: "Admin" }),
4955
- /* @__PURE__ */ jsx(SelectItem, { value: "editor", children: "Editor" }),
4956
- /* @__PURE__ */ jsx(SelectItem, { value: "viewer", children: "Viewer" }),
4957
- /* @__PURE__ */ jsx(SelectItem, { value: "guest", children: "Guest" })
4958
- ] })
4959
- ] }) }),
4960
- /* @__PURE__ */ jsx(DataBodyTemplate.Row, { label: "Department", children: /* @__PURE__ */ jsxs(Select, { defaultValue: "engineering", children: [
4961
- /* @__PURE__ */ jsx(SelectTrigger, { className: "h-8 text-sm", children: /* @__PURE__ */ jsx(SelectValue, {}) }),
4962
- /* @__PURE__ */ jsxs(SelectContent, { children: [
4963
- /* @__PURE__ */ jsx(SelectItem, { value: "engineering", children: "Engineering" }),
4964
- /* @__PURE__ */ jsx(SelectItem, { value: "design", children: "Design" }),
4965
- /* @__PURE__ */ jsx(SelectItem, { value: "product", children: "Product" }),
4966
- /* @__PURE__ */ jsx(SelectItem, { value: "marketing", children: "Marketing" })
4967
- ] })
4968
- ] }) }),
4969
- /* @__PURE__ */ jsx(DataBodyTemplate.Row, { label: "Active", description: "Inactive users cannot sign in.", children: /* @__PURE__ */ jsx(Switch, { defaultChecked: true }) }),
4970
- /* @__PURE__ */ jsx(DataBodyTemplate.Row, { label: "Require 2FA", description: "Enforce two-factor authentication.", children: /* @__PURE__ */ jsx(Switch, {}) })
4971
- ] }),
4972
- /* @__PURE__ */ jsxs(DataBodyTemplate.Group, { layout: "inline", title: "Address", children: [
4973
- /* @__PURE__ */ jsx(DataBodyTemplate.Row, { label: "Country", children: /* @__PURE__ */ jsxs(Select, { defaultValue: "kr", children: [
4974
- /* @__PURE__ */ jsx(SelectTrigger, { className: "h-8 text-sm", children: /* @__PURE__ */ jsx(SelectValue, {}) }),
4975
- /* @__PURE__ */ jsxs(SelectContent, { children: [
4976
- /* @__PURE__ */ jsx(SelectItem, { value: "kr", children: "South Korea" }),
4977
- /* @__PURE__ */ jsx(SelectItem, { value: "us", children: "United States" }),
4978
- /* @__PURE__ */ jsx(SelectItem, { value: "jp", children: "Japan" }),
4979
- /* @__PURE__ */ jsx(SelectItem, { value: "gb", children: "United Kingdom" })
4980
- ] })
4981
- ] }) }),
4982
- /* @__PURE__ */ jsx(DataBodyTemplate.Row, { label: "City", children: /* @__PURE__ */ jsx(Input, { defaultValue: "Seoul", className: "h-8 text-sm" }) }),
4983
- /* @__PURE__ */ jsx(DataBodyTemplate.Row, { label: "Postal Code", children: /* @__PURE__ */ jsx(Input, { defaultValue: "04524", className: "h-8 text-sm w-36" }) })
4984
- ] }),
4985
- /* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-2 px-(--dk-page-padding-x) pb-(--dk-page-padding-y)", children: [
4986
- /* @__PURE__ */ jsx(Button, { type: "reset", variant: "outline", size: "sm", className: "h-8 text-xs", children: "Cancel" }),
4987
- /* @__PURE__ */ jsx(Button, { type: "submit", size: "sm", className: "h-8 text-xs", children: "Save" })
4988
- ] })
4989
- ] })
3255
+ "data-slot": "breadcrumb-item",
3256
+ className: cn("inline-flex items-center gap-1", className),
3257
+ ...props
4990
3258
  }
4991
3259
  );
4992
3260
  }
4993
- function buildFormInlineBodyTemplateCode({
4994
- themeProp,
4995
- layoutClassName
3261
+ function BreadcrumbLink({
3262
+ className,
3263
+ render,
3264
+ ...props
4996
3265
  }) {
4997
- return [
4998
- `import { DataBodyTemplate } from '@loykin/designkit'`,
4999
- `import '@loykin/designkit/styles'`,
5000
- "",
5001
- `export function MyPage() {`,
5002
- ` return (`,
5003
- ` <DataBodyTemplate${themeProp}`,
5004
- ` className="${layoutClassName}"`,
5005
- ` title="Edit User"`,
5006
- ` >`,
5007
- ` <form onSubmit={handleSubmit} className="contents">`,
5008
- ` <DataBodyTemplate.Group layout="inline" title="Identity">`,
5009
- ` <DataBodyTemplate.Row label="Field" required>`,
5010
- ` {/* input */}`,
5011
- ` </DataBodyTemplate.Row>`,
5012
- ` </DataBodyTemplate.Group>`,
5013
- ` <div className="flex justify-end gap-2 px-(--dk-page-padding-x) pb-(--dk-page-padding-y)">`,
5014
- ` <button type="reset">Cancel</button>`,
5015
- ` <button type="submit">Save</button>`,
5016
- ` </div>`,
5017
- ` </form>`,
5018
- ` </DataBodyTemplate>`,
5019
- ` )`,
5020
- `}`
5021
- ].join("\n");
5022
- }
5023
- function SectionedBodyTemplateDemo({ theme, topBarShow, topBarVariant, topBarBg }) {
5024
- return /* @__PURE__ */ jsxs(
5025
- DataBodyTemplate,
5026
- {
5027
- theme,
5028
- topBar: buildTopBar({ topBarShow, topBarVariant, topBarBg, left: "Pages / Sectioned" }),
5029
- title: "Workspace Settings",
5030
- description: "Section navigation connected to body panels.",
5031
- children: [
5032
- /* @__PURE__ */ jsx(DataBodyTemplate.Section, { id: "profile", label: "Profile", description: "Identity and contact", children: /* @__PURE__ */ jsx(
5033
- DataBodyTemplate.Group,
5034
- {
5035
- layout: "stacked",
5036
- title: "Profile",
5037
- description: "Public workspace details.",
5038
- children: /* @__PURE__ */ jsxs("form", { onSubmit: (e) => e.preventDefault(), className: "space-y-3", children: [
5039
- /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
5040
- /* @__PURE__ */ jsx(Label, { htmlFor: "workspace-name", className: "text-xs", children: "Workspace Name" }),
5041
- /* @__PURE__ */ jsx(Input, { id: "workspace-name", defaultValue: "Acme Corp", className: "h-8 text-sm" })
5042
- ] }),
5043
- /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
5044
- /* @__PURE__ */ jsxs("div", { children: [
5045
- /* @__PURE__ */ jsx("p", { className: "text-sm font-medium", children: "Public profile" }),
5046
- /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: "Allow discovery in organization search." })
5047
- ] }),
5048
- /* @__PURE__ */ jsx(Switch, { defaultChecked: true })
5049
- ] }),
5050
- /* @__PURE__ */ jsx("div", { className: "flex justify-end", children: /* @__PURE__ */ jsx(Button, { type: "submit", size: "sm", className: "h-8 text-xs", children: "Save" }) })
5051
- ] })
5052
- }
5053
- ) }),
5054
- /* @__PURE__ */ jsx(DataBodyTemplate.Section, { id: "security", label: "Security", description: "Password and access", children: /* @__PURE__ */ jsx(
5055
- DataBodyTemplate.Group,
5056
- {
5057
- layout: "stacked",
5058
- title: "Security",
5059
- description: "Password and authentication.",
5060
- children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
5061
- /* @__PURE__ */ jsx("p", { className: "text-sm font-medium", children: "Require two-factor authentication" }),
5062
- /* @__PURE__ */ jsx(Switch, {})
5063
- ] })
5064
- }
5065
- ) }),
5066
- /* @__PURE__ */ jsx(DataBodyTemplate.Section, { id: "billing", label: "Billing", description: "Plan and invoices", children: /* @__PURE__ */ jsx(
5067
- DataBodyTemplate.Group,
5068
- {
5069
- layout: "stacked",
5070
- title: "Billing",
5071
- description: "Plan and invoice settings.",
5072
- children: /* @__PURE__ */ jsx(Button, { variant: "outline", size: "sm", className: "h-8 text-xs", children: "Manage Plan" })
5073
- }
5074
- ) })
5075
- ]
3266
+ return useRender({
3267
+ defaultTagName: "a",
3268
+ props: mergeProps(
3269
+ {
3270
+ className: cn("transition-colors hover:text-foreground", className)
3271
+ },
3272
+ props
3273
+ ),
3274
+ render,
3275
+ state: {
3276
+ slot: "breadcrumb-link"
5076
3277
  }
5077
- );
3278
+ });
5078
3279
  }
5079
- function buildSectionedBodyTemplateCode({
5080
- themeProp,
5081
- layoutClassName
5082
- }) {
5083
- return [
5084
- `import { DataBodyTemplate } from '@loykin/designkit'`,
5085
- `import '@loykin/designkit/styles'`,
5086
- "",
5087
- `export function MyPage() {`,
5088
- ` return (`,
5089
- ` <DataBodyTemplate${themeProp}`,
5090
- ` className="${layoutClassName}"`,
5091
- ` title="Workspace Settings"`,
5092
- ` actions={<button type="button">Save</button>}`,
5093
- ` >`,
5094
- ` <DataBodyTemplate.Section id="profile" label="Profile" description="Identity and contact">`,
5095
- ` <DataBodyTemplate.Group layout="stacked" title="Profile">`,
5096
- ` {/* form fields */}`,
5097
- ` </DataBodyTemplate.Group>`,
5098
- ` </DataBodyTemplate.Section>`,
5099
- ``,
5100
- ` <DataBodyTemplate.Section id="security" label="Security" description="Password and access">`,
5101
- ` <DataBodyTemplate.Group layout="stacked" title="Security">`,
5102
- ` {/* security fields */}`,
5103
- ` </DataBodyTemplate.Group>`,
5104
- ` </DataBodyTemplate.Section>`,
5105
- ` </DataBodyTemplate>`,
5106
- ` )`,
5107
- `}`
5108
- ].join("\n");
5109
- }
5110
- function LoginBodyTemplateDemo({
5111
- theme,
5112
- loginLayout,
5113
- loginSide,
5114
- loginCard,
5115
- loginBg,
5116
- loginCardWidth
5117
- }) {
3280
+ function BreadcrumbPage({ className, ...props }) {
5118
3281
  return /* @__PURE__ */ jsx(
5119
- LoginBodyTemplate,
3282
+ "span",
5120
3283
  {
5121
- theme,
5122
- layout: loginLayout ?? "centered",
5123
- side: loginSide ?? "left",
5124
- card: loginCard ?? "card",
5125
- bg: loginBg ?? "default",
5126
- cardWidth: loginCardWidth ?? "sm",
5127
- children: /* @__PURE__ */ jsxs("form", { className: "space-y-6", onSubmit: (e) => e.preventDefault(), children: [
5128
- /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
5129
- /* @__PURE__ */ jsx("h1", { className: "text-2xl font-semibold tracking-tight", children: "Sign in" }),
5130
- /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: "Enter your email and password to continue." })
5131
- ] }),
5132
- /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
5133
- /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
5134
- /* @__PURE__ */ jsx(Label, { htmlFor: "email", className: "text-xs", children: "Email" }),
5135
- /* @__PURE__ */ jsx(Input, { id: "email", type: "email", placeholder: "you@example.com", className: "h-9" })
5136
- ] }),
5137
- /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
5138
- /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
5139
- /* @__PURE__ */ jsx(Label, { htmlFor: "password", className: "text-xs", children: "Password" }),
5140
- /* @__PURE__ */ jsx("a", { href: "#", className: "text-xs text-muted-foreground hover:text-foreground transition-colors", children: "Forgot password?" })
5141
- ] }),
5142
- /* @__PURE__ */ jsx(Input, { id: "password", type: "password", placeholder: "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022", className: "h-9" })
5143
- ] }),
5144
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
5145
- /* @__PURE__ */ jsx(Checkbox, { id: "remember" }),
5146
- /* @__PURE__ */ jsx(Label, { htmlFor: "remember", className: "text-xs font-normal text-muted-foreground cursor-pointer", children: "Remember me for 30 days" })
5147
- ] })
5148
- ] }),
5149
- /* @__PURE__ */ jsx(Button, { type: "submit", className: "w-full h-9", children: "Sign in" }),
5150
- /* @__PURE__ */ jsxs("p", { className: "text-center text-xs text-muted-foreground", children: [
5151
- "Don't have an account?",
5152
- " ",
5153
- /* @__PURE__ */ jsx("a", { href: "#", className: "text-foreground hover:underline", children: "Sign up" })
5154
- ] })
5155
- ] })
3284
+ "data-slot": "breadcrumb-page",
3285
+ role: "link",
3286
+ "aria-disabled": "true",
3287
+ "aria-current": "page",
3288
+ className: cn("font-normal text-foreground", className),
3289
+ ...props
5156
3290
  }
5157
3291
  );
5158
3292
  }
5159
- function buildLoginBodyTemplateCode({ themeProp }) {
5160
- return [
5161
- `import { LoginBodyTemplate } from '@loykin/designkit'`,
5162
- `import '@loykin/designkit/styles'`,
5163
- "",
5164
- `export function LoginPage() {`,
5165
- ` return (`,
5166
- ` <LoginBodyTemplate${themeProp} layout="split">`,
5167
- ` <div className="space-y-6">`,
5168
- ` <div className="space-y-1.5">`,
5169
- ` <h1 className="text-2xl font-semibold">Sign in</h1>`,
5170
- ` <p className="text-sm text-muted-foreground">Enter your credentials.</p>`,
5171
- ` </div>`,
5172
- ` {/* form fields */}`,
5173
- ` <button type="submit" className="w-full">Sign in</button>`,
5174
- ` </div>`,
5175
- ` </LoginBodyTemplate>`,
5176
- ` )`,
5177
- `}`
5178
- ].join("\n");
5179
- }
5180
- function LoginForgotDemo({
5181
- theme,
5182
- loginLayout,
5183
- loginSide,
5184
- loginCard,
5185
- loginBg,
5186
- loginCardWidth
3293
+ function BreadcrumbSeparator({
3294
+ children,
3295
+ className,
3296
+ ...props
5187
3297
  }) {
5188
3298
  return /* @__PURE__ */ jsx(
5189
- LoginBodyTemplate,
3299
+ "li",
5190
3300
  {
5191
- theme,
5192
- layout: loginLayout ?? "centered",
5193
- side: loginSide ?? "left",
5194
- card: loginCard ?? "card",
5195
- bg: loginBg ?? "default",
5196
- cardWidth: loginCardWidth ?? "sm",
5197
- children: /* @__PURE__ */ jsxs("form", { className: "space-y-6", onSubmit: (e) => e.preventDefault(), children: [
5198
- /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
5199
- /* @__PURE__ */ jsx("h1", { className: "text-2xl font-semibold tracking-tight", children: "Forgot password?" }),
5200
- /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: "Enter your email and we'll send you a reset link." })
5201
- ] }),
5202
- /* @__PURE__ */ jsx("div", { className: "space-y-3", children: /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
5203
- /* @__PURE__ */ jsx(Label, { htmlFor: "email", className: "text-xs", children: "Email" }),
5204
- /* @__PURE__ */ jsx(Input, { id: "email", type: "email", placeholder: "you@example.com", className: "h-9" })
5205
- ] }) }),
5206
- /* @__PURE__ */ jsx(Button, { type: "submit", className: "w-full h-9", children: "Send reset link" }),
5207
- /* @__PURE__ */ jsxs(
5208
- "a",
5209
- {
5210
- href: "#",
5211
- className: "flex items-center justify-center gap-1.5 text-xs text-muted-foreground hover:text-foreground transition-colors",
5212
- children: [
5213
- /* @__PURE__ */ jsx(ArrowLeft, { className: "h-3.5 w-3.5" }),
5214
- "Back to sign in"
5215
- ]
5216
- }
5217
- )
5218
- ] })
3301
+ "data-slot": "breadcrumb-separator",
3302
+ role: "presentation",
3303
+ "aria-hidden": "true",
3304
+ className: cn("[&>svg]:size-3.5", className),
3305
+ ...props,
3306
+ children: children ?? /* @__PURE__ */ jsx(ChevronRightIcon, {})
5219
3307
  }
5220
3308
  );
5221
3309
  }
5222
- function buildLoginForgotCode({ themeProp }) {
5223
- return [
5224
- `import { LoginBodyTemplate } from '@loykin/designkit'`,
5225
- `import '@loykin/designkit/styles'`,
5226
- "",
5227
- `export function ForgotPasswordPage() {`,
5228
- ` return (`,
5229
- ` <LoginBodyTemplate${themeProp} layout="split">`,
5230
- ` <div className="space-y-6">`,
5231
- ` <div className="space-y-1.5">`,
5232
- ` <h1 className="text-2xl font-semibold">Forgot password?</h1>`,
5233
- ` <p className="text-sm text-muted-foreground">We'll send you a reset link.</p>`,
5234
- ` </div>`,
5235
- ` {/* email input */}`,
5236
- ` <button type="submit" className="w-full">Send reset link</button>`,
5237
- ` </div>`,
5238
- ` </LoginBodyTemplate>`,
5239
- ` )`,
5240
- `}`
5241
- ].join("\n");
5242
- }
5243
- function LoginResetDemo({
5244
- theme,
5245
- loginLayout,
5246
- loginSide,
5247
- loginCard,
5248
- loginBg,
5249
- loginCardWidth
5250
- }) {
3310
+ function PageBreadcrumb({ items }) {
3311
+ return /* @__PURE__ */ jsx(Breadcrumb, { children: /* @__PURE__ */ jsx(BreadcrumbList, { className: "text-xs gap-1", children: items.map((item, i) => {
3312
+ const isLast = i === items.length - 1;
3313
+ const label = typeof item === "string" ? item : item.label;
3314
+ const href = typeof item === "string" ? void 0 : item.href;
3315
+ return /* @__PURE__ */ jsxs(React2__default.Fragment, { children: [
3316
+ i > 0 && /* @__PURE__ */ jsx(BreadcrumbSeparator, {}),
3317
+ /* @__PURE__ */ jsx(BreadcrumbItem, { children: isLast ? /* @__PURE__ */ jsx(BreadcrumbPage, { className: "text-xs", children: label }) : href ? /* @__PURE__ */ jsx(BreadcrumbLink, { href, className: "text-xs", children: label }) : /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: label }) })
3318
+ ] }, i);
3319
+ }) }) });
3320
+ }
3321
+ function normalizeBreadcrumb(left) {
3322
+ if (typeof left === "string") {
3323
+ const items = left.split("/").map((s) => s.trim()).filter(Boolean);
3324
+ return /* @__PURE__ */ jsx(PageBreadcrumb, { items });
3325
+ }
3326
+ return left;
3327
+ }
3328
+ var bgClassMap = {
3329
+ muted: "bg-muted",
3330
+ card: "bg-card",
3331
+ transparent: ""
3332
+ };
3333
+ function buildTopBar(opts) {
3334
+ if (opts.topBarShow === "hide") return void 0;
5251
3335
  return /* @__PURE__ */ jsx(
5252
- LoginBodyTemplate,
3336
+ PageTopBar,
5253
3337
  {
5254
- theme,
5255
- layout: loginLayout ?? "centered",
5256
- side: loginSide ?? "left",
5257
- card: loginCard ?? "card",
5258
- bg: loginBg ?? "default",
5259
- cardWidth: loginCardWidth ?? "sm",
5260
- children: /* @__PURE__ */ jsxs("form", { className: "space-y-6", onSubmit: (e) => e.preventDefault(), children: [
5261
- /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
5262
- /* @__PURE__ */ jsx("h1", { className: "text-2xl font-semibold tracking-tight", children: "Set new password" }),
5263
- /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: "Must be at least 8 characters." })
5264
- ] }),
5265
- /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
5266
- /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
5267
- /* @__PURE__ */ jsx(Label, { htmlFor: "new-password", className: "text-xs", children: "New Password" }),
5268
- /* @__PURE__ */ jsx(Input, { id: "new-password", type: "password", placeholder: "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022", className: "h-9" })
5269
- ] }),
5270
- /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
5271
- /* @__PURE__ */ jsx(Label, { htmlFor: "confirm-password", className: "text-xs", children: "Confirm Password" }),
5272
- /* @__PURE__ */ jsx(Input, { id: "confirm-password", type: "password", placeholder: "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022", className: "h-9" })
5273
- ] }),
5274
- /* @__PURE__ */ jsx("div", { className: "space-y-1.5 pt-1", children: ["At least 8 characters", "One uppercase letter", "One number"].map((rule) => /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-xs text-muted-foreground", children: [
5275
- /* @__PURE__ */ jsx(CheckCircle2, { className: "h-3.5 w-3.5 shrink-0" }),
5276
- rule
5277
- ] }, rule)) })
5278
- ] }),
5279
- /* @__PURE__ */ jsx(Button, { type: "submit", className: "w-full h-9", children: "Update password" })
5280
- ] })
3338
+ left: normalizeBreadcrumb(opts.left),
3339
+ right: opts.right,
3340
+ variant: opts.topBarVariant ?? "ghost",
3341
+ className: bgClassMap[opts.topBarBg ?? "transparent"] ?? ""
5281
3342
  }
5282
3343
  );
5283
3344
  }
5284
- function buildLoginResetCode({ themeProp }) {
5285
- return [
5286
- `import { LoginBodyTemplate } from '@loykin/designkit'`,
5287
- `import '@loykin/designkit/styles'`,
5288
- "",
5289
- `export function ResetPasswordPage() {`,
5290
- ` return (`,
5291
- ` <LoginBodyTemplate${themeProp} layout="split">`,
5292
- ` <div className="space-y-6">`,
5293
- ` <h1 className="text-2xl font-semibold">Set new password</h1>`,
5294
- ` {/* password inputs */}`,
5295
- ` <button type="submit" className="w-full">Update password</button>`,
5296
- ` </div>`,
5297
- ` </LoginBodyTemplate>`,
5298
- ` )`,
5299
- `}`
5300
- ].join("\n");
5301
- }
5302
- function LoginOtpDemo({
5303
- theme,
5304
- loginLayout,
5305
- loginSide,
5306
- loginCard,
5307
- loginBg,
5308
- loginCardWidth
3345
+ function PageTopBar({
3346
+ left,
3347
+ right,
3348
+ variant = "ghost",
3349
+ height = "var(--dk-toolbar-height)",
3350
+ className,
3351
+ style,
3352
+ children
5309
3353
  }) {
5310
- return /* @__PURE__ */ jsx(
5311
- LoginBodyTemplate,
3354
+ return /* @__PURE__ */ jsxs(
3355
+ "div",
5312
3356
  {
5313
- theme,
5314
- layout: loginLayout ?? "centered",
5315
- side: loginSide ?? "left",
5316
- card: loginCard ?? "card",
5317
- bg: loginBg ?? "default",
5318
- cardWidth: loginCardWidth ?? "sm",
5319
- children: /* @__PURE__ */ jsxs("form", { className: "space-y-6", onSubmit: (e) => e.preventDefault(), children: [
5320
- /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
5321
- /* @__PURE__ */ jsx("h1", { className: "text-2xl font-semibold tracking-tight", children: "Check your email" }),
5322
- /* @__PURE__ */ jsxs("p", { className: "text-sm text-muted-foreground", children: [
5323
- "We sent a 6-digit code to",
5324
- " ",
5325
- /* @__PURE__ */ jsx("span", { className: "font-medium text-foreground", children: "sarah@acme.com" })
5326
- ] })
5327
- ] }),
5328
- /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
5329
- /* @__PURE__ */ jsx("div", { className: "flex gap-2", children: Array.from({ length: 6 }).map((_, i) => /* @__PURE__ */ jsx(
5330
- Input,
5331
- {
5332
- maxLength: 1,
5333
- className: "h-11 w-full text-center text-lg font-semibold tabular-nums p-0",
5334
- defaultValue: i < 3 ? ["4", "8", "2"][i] : ""
5335
- },
5336
- i
5337
- )) }),
5338
- /* @__PURE__ */ jsxs("p", { className: "text-xs text-muted-foreground text-center", children: [
5339
- "Didn't receive it?",
5340
- " ",
5341
- /* @__PURE__ */ jsx("a", { href: "#", className: "text-foreground hover:underline", children: "Resend code" }),
5342
- " ",
5343
- /* @__PURE__ */ jsx("span", { className: "text-muted-foreground/60", children: "(59s)" })
5344
- ] })
5345
- ] }),
5346
- /* @__PURE__ */ jsx(Button, { type: "submit", className: "w-full h-9", children: "Verify" }),
5347
- /* @__PURE__ */ jsxs(
5348
- "a",
5349
- {
5350
- href: "#",
5351
- className: "flex items-center justify-center gap-1.5 text-xs text-muted-foreground hover:text-foreground transition-colors",
5352
- children: [
5353
- /* @__PURE__ */ jsx(ArrowLeft, { className: "h-3.5 w-3.5" }),
5354
- "Back to sign in"
5355
- ]
5356
- }
5357
- )
5358
- ] })
3357
+ className: cn(
3358
+ "flex shrink-0 items-center justify-between gap-4 px-(--dk-page-padding-x)",
3359
+ variant === "default" && "border-b",
3360
+ className
3361
+ ),
3362
+ style: { height, ...style },
3363
+ children: [
3364
+ /* @__PURE__ */ jsx("div", { className: "flex min-w-0 items-center text-xs text-muted-foreground", children: normalizeBreadcrumb(left ?? children) }),
3365
+ right && /* @__PURE__ */ jsx("div", { className: "flex shrink-0 items-center gap-2", children: right })
3366
+ ]
5359
3367
  }
5360
3368
  );
5361
3369
  }
5362
- function buildLoginOtpCode({ themeProp }) {
5363
- return [
5364
- `import { LoginBodyTemplate } from '@loykin/designkit'`,
5365
- `import '@loykin/designkit/styles'`,
5366
- "",
5367
- `export function OtpVerificationPage() {`,
5368
- ` return (`,
5369
- ` <LoginBodyTemplate${themeProp} layout="split">`,
5370
- ` <div className="space-y-6">`,
5371
- ` <h1 className="text-2xl font-semibold">Check your email</h1>`,
5372
- ` {/* otp inputs */}`,
5373
- ` <button type="submit" className="w-full">Verify</button>`,
5374
- ` </div>`,
5375
- ` </LoginBodyTemplate>`,
5376
- ` )`,
5377
- `}`
5378
- ].join("\n");
5379
- }
5380
-
5381
- // src/components/templates/index.ts
5382
- function DataGridTemplatePreview(props) {
5383
- return createElement(DataGridTemplateDemo, props);
5384
- }
5385
- function createDataGridPreview(id) {
5386
- const definition = TEMPLATE_DEFINITIONS.find((item) => item.id === id);
5387
- return function DataGridPreview({
5388
- theme,
5389
- topBarShow,
5390
- topBarVariant,
5391
- topBarBg
5392
- }) {
5393
- return createElement(DataGridTemplatePreview, {
5394
- theme,
5395
- variant: definition?.preview?.variant ?? "standard",
5396
- layoutClassName: definition?.layoutClassName ?? `layout-${id}`,
5397
- title: definition?.preview?.title ?? "Users",
5398
- description: definition?.preview?.description,
5399
- topBarShow,
5400
- topBarVariant,
5401
- topBarBg
5402
- });
5403
- };
5404
- }
5405
- var previewComponents = {
5406
- table: createDataGridPreview("table"),
5407
- "table-infinity": createDataGridPreview("table-infinity"),
5408
- "table-drag": createDataGridPreview("table-drag"),
5409
- "table-card": createDataGridPreview("table-card"),
5410
- "table-card-list": createDataGridPreview("table-card-list"),
5411
- databody: DataBodyTemplateDemo,
5412
- "databody-detail": DetailBodyTemplateDemo,
5413
- "databody-split": SplitBodyTemplateDemo,
5414
- tabbed: TabbedBodyTemplateDemo,
5415
- form: FormBodyTemplateDemo,
5416
- "form-stacked": FormStackedBodyTemplateDemo,
5417
- "form-wizard": FormWizardBodyTemplateDemo,
5418
- "form-inline": FormInlineBodyTemplateDemo,
5419
- sectioned: SectionedBodyTemplateDemo,
5420
- typography: TypographyBodyTemplate,
5421
- colors: ColorsBodyTemplate,
5422
- login: LoginBodyTemplateDemo,
5423
- "login-forgot": LoginForgotDemo,
5424
- "login-reset": LoginResetDemo,
5425
- "login-otp": LoginOtpDemo
5426
- };
5427
- var codeBuilders = {
5428
- table: buildDataGridTemplateCode,
5429
- "table-infinity": buildDataGridTemplateCode,
5430
- "table-drag": buildDataGridTemplateCode,
5431
- "table-card": buildDataGridTemplateCode,
5432
- "table-card-list": buildDataGridTemplateCode,
5433
- databody: buildDataBodyTemplateCode,
5434
- "databody-detail": buildDetailBodyTemplateCode,
5435
- "databody-split": buildSplitBodyTemplateCode,
5436
- tabbed: buildTabbedBodyTemplateCode,
5437
- form: buildFormBodyTemplateCode,
5438
- "form-stacked": buildFormStackedBodyTemplateCode,
5439
- "form-wizard": buildFormWizardBodyTemplateCode,
5440
- login: buildLoginBodyTemplateCode,
5441
- "login-forgot": buildLoginForgotCode,
5442
- "login-reset": buildLoginResetCode,
5443
- "login-otp": buildLoginOtpCode,
5444
- "form-inline": buildFormInlineBodyTemplateCode,
5445
- sectioned: buildSectionedBodyTemplateCode
5446
- };
5447
- var TEMPLATES = TEMPLATE_DEFINITIONS.map((definition) => ({
5448
- id: definition.id,
5449
- label: definition.label,
5450
- group: definition.group,
5451
- component: previewComponents[definition.id],
5452
- buildCode: codeBuilders[definition.id]
5453
- }));
5454
- var iconById = {
5455
- table: Table2,
5456
- "table-card": Layers,
5457
- databody: LayoutDashboard,
5458
- sectioned: FileText,
5459
- form: FileText,
5460
- "form-wizard": FileText,
5461
- typography: Type,
5462
- colors: Palette,
5463
- login: KeyRound
5464
- };
5465
- var navigationGroupIcon = {
5466
- DataBodyTemplate: LayoutDashboard,
5467
- FormWizardBodyTemplate: Layers,
5468
- LoginBodyTemplate: KeyRound
5469
- };
5470
- var navigationLabelOrder = ["Common", "DataBodyTemplate", "FormWizardBodyTemplate", "LoginBodyTemplate"];
5471
- var TEMPLATE_NAVIGATION = navigationLabelOrder.map((groupId) => {
5472
- const definitions = TEMPLATE_DEFINITIONS.filter((d) => d.navigationGroup === groupId);
5473
- const parentDefinitions = definitions.filter((d) => !d.navigationParent);
5474
- const label = groupId;
5475
- return {
5476
- label,
5477
- items: parentDefinitions.map((definition) => {
5478
- const childDefs = definitions.filter((d) => d.navigationParent === definition.id);
5479
- const hasChildren = childDefs.length > 0;
5480
- return {
5481
- id: definition.id,
5482
- label: definition.navigationSubgroupLabel ?? definition.navigationLabel ?? definition.label,
5483
- icon: iconById[definition.id] ?? navigationGroupIcon[label],
5484
- children: hasChildren ? [
5485
- { id: definition.id, label: definition.navigationLabel ?? definition.label },
5486
- ...childDefs.map((child) => ({
5487
- id: child.id,
5488
- label: child.navigationLabel ?? child.label
5489
- }))
5490
- ] : []
5491
- };
5492
- })
5493
- };
5494
- }).filter((group) => group.items.length > 0);
5495
3370
  var STYLE_ID = "designkit-vars";
5496
3371
  function buildTokenMap({
5497
3372
  radius,
@@ -5644,7 +3519,7 @@ ${tokenMapToCss(buildDarkTonalTokens(g.primaryHue, g.primaryChroma))}
5644
3519
  panelGap: o.panelGap,
5645
3520
  toolbarHeight: o.toolbarHeight
5646
3521
  });
5647
- const layoutClassName = getTemplateDefinition(id)?.layoutClassName ?? `layout-${id}`;
3522
+ const layoutClassName = `layout-${id}`;
5648
3523
  return `.${layoutClassName} {
5649
3524
  ${tokenMapToCss(tokens)}
5650
3525
  }`;
@@ -5676,6 +3551,6 @@ function buildTemplateTheme(g, ov = {}) {
5676
3551
  });
5677
3552
  }
5678
3553
 
5679
- export { Avatar, AvatarBadge, AvatarFallback, AvatarGroup, AvatarGroupCount, AvatarImage, Badge, Button, Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Checkbox, ColorsBodyTemplate, DataBodyTemplate, DataBodyTemplateDemo, DataGridView, DataPage, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EmptyState, FormWizardBodyTemplate, FormWizardBodyTemplateDemo, Input, Label, LoginBodyTemplate, NavigationMenu, NavigationMenuContent, NavigationMenuIndicator, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, NavigationMenuPositioner, NavigationMenuTrigger, PageBreadcrumb, PageTopBar, Popover, PopoverContent, PopoverDescription, PopoverHeader, PopoverTitle, PopoverTrigger, ScrollArea, ScrollBar, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Separator, Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger, Sidebar, SidebarContent, SidebarFooter, SidebarGroup, SidebarGroupAction, SidebarGroupContent, SidebarGroupLabel, SidebarHeader, SidebarInput, SidebarInset, SidebarMenu, SidebarMenuAction, SidebarMenuBadge, SidebarMenuButton, SidebarMenuItem, SidebarMenuSkeleton, SidebarMenuSub, SidebarMenuSubButton, SidebarMenuSubItem, SidebarProvider, SidebarRail, SidebarSeparator, SidebarTrigger, Skeleton, Slider, Switch, TEMPLATES, TEMPLATE_DEFINITIONS, TEMPLATE_NAVIGATION, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, TypographyBodyTemplate, badgeVariants, buildTemplateTheme, buildTopBar, buttonVariants, cn, createTemplateOverrides, getTemplateDefinition, navigationMenuTriggerStyle, tabsListVariants, useIsMobile, useSidebar, useStyleInjector, useThemeStore };
3554
+ export { Avatar, AvatarBadge, AvatarFallback, AvatarGroup, AvatarGroupCount, AvatarImage, Badge, BrowseBodyTemplate, Button, Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Checkbox, ColorsBodyTemplate, DashboardBodyTemplate, DashboardPanel, DataBodyTemplate, DataPage, DetailBodyTemplate, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EmptyState, FormWizardBodyTemplate, Input, Label, LoginBodyTemplate, NavigationMenu, NavigationMenuContent, NavigationMenuIndicator, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, NavigationMenuPositioner, NavigationMenuTrigger, PageBreadcrumb, PageTopBar, Popover, PopoverContent, PopoverDescription, PopoverHeader, PopoverTitle, PopoverTrigger, ScrollArea, ScrollBar, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Separator, Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger, Sidebar, SidebarContent, SidebarFooter, SidebarGroup, SidebarGroupAction, SidebarGroupContent, SidebarGroupLabel, SidebarHeader, SidebarInput, SidebarInset, SidebarMenu, SidebarMenuAction, SidebarMenuBadge, SidebarMenuButton, SidebarMenuItem, SidebarMenuSkeleton, SidebarMenuSub, SidebarMenuSubButton, SidebarMenuSubItem, SidebarProvider, SidebarRail, SidebarSeparator, SidebarTrigger, Skeleton, Slider, Switch, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, TypographyBodyTemplate, badgeVariants, buildTemplateTheme, buildTopBar, buttonVariants, cn, navigationMenuTriggerStyle, tabsListVariants, useIsMobile, useSidebar, useStyleInjector, useThemeStore };
5680
3555
  //# sourceMappingURL=index.js.map
5681
3556
  //# sourceMappingURL=index.js.map